
What’s the best way to calculate the startup time of a racket program? I notice that when I do racket myprogram.rkt x y z
, sometimes it looks like my program only really starts after 7secs or so. That’s a lot. My program takes less than that to complete.

More raco pkg
questions; what’s the usefulness of the --scope-dir
option? When I use it for installing a pkg, I noticed that the package dependency resolution process seems to ignore the installation and user scopes and raco pkg
will try to download pkgs that are already installed in installation scope. That seems to reduce the utility of --scope-dir
so I was wondering what use cases --scope-dir
is meant to support.

quick date
manipulation question in Racket: is there a function that lets me compute e.g. “February 27, 2018 plus 3 days yields March 2, 2018”? I’d like to be able to fold starting from an initial date and some list of deltas (2 days later, 1 day later, 4 days later, etc) and compute all the valid dates along the way

(I don’t care about string manipulation; I assume the racket/date
library’s date->string
function will suffice from there)

consider using the gregor
library instead of racket/date
/ srfi/19

that’ll do it, thanks

I am trying to get an identifier whose binding is a particular module. And it seems like combining module->namespace
with namespace-symbol->identifier
does the trick at phase 0. But at phase 1 I am getting the same #%top
undefined error.



Obviously if you remove the begin-for-syntax
Its properly bound.

I wonder if I’m still doing overly strange stuff @mflatt?

Also, if I do a syntax-shift-phase-level
by -1
, it is able to find the binding again.

Which makes me think that the one of those two namespace functions aren’t properly shifting the phases given that they’re in a begin-for-syntax.

@leif While running at phase N for N > 0, identifier-binding
implicitly checks bindings at phase N–1 (because the expectation is that you’re using identifier-binding
at compile time to inspect run-time code), while namespace operations work at the current phase N (because the expectation is that you’re dynamically loading code at the current phase). So that’s why shifting by –1 does what you want. Another possibility is to supply the current phase to identifier-binding
, where (variable-reference->phase (#%variable-reference))
is one way to get the current phase.

I guess that makes sense. But then why does the following macro complain about the match identifier being unbound?:
(define-syntax (my-m stx)
(dynamic-require 'racket/match 0)
(define x
(parameterize ([current-namespace (module->namespace 'racket/match)])
(namespace-symbol->identifier 'match)))
x)

Since the namespace operations in the macro happen at phase 1, the match
identifier will have a binding at phase 1 and not at phase 0.

That would make sense, but if I shift it down a phase with: (define x
(syntax-shift-phase-level
(parameterize ([current-namespace (module->namespace 'racket/match)])
(namespace-symbol->identifier 'match))
-1))

then I get an error saying the module is not available: require: namespace mismatch;
reference to a module that is not available
reference phase: 0
referenced module: "/Users/leif/racket/racket/collects/racket/match/match.rkt"
referenced phase level: 0
in: match
context...:
/Users/leif/racket/racket/collects/syntax/wrap-modbeg.rkt:46:4
standard-module-name-resolver

Yes, that is a correct error. Since you’re manipulating the phase of the syntax object, you’re breaking the connection between the instantiation of the source module and the reference to that module.

But, for example, if you (require match)
in a phase–0 position (such as in the same place where my-m
is defined), then match
will be available.

That would make sense. I however don’t want to do that because (as I understand it), that would bring match
in as an identifier for the rest of the module.

I did try a dynamic-require in the template, but that gave the same error.

A (require (only-in match))
would make the module available without binding anything

OH!!!

That’s a great idea.

Thanks.

Or something like (namespace-require '(for-template racket/match))
in the macro

Oh cool, that worked, thanks: (define-syntax (my-m stx)
(dynamic-require 'racket/match 0)
(define x
(syntax-shift-phase-level
(parameterize ([current-namespace (module->namespace 'racket/match)])
(namespace-symbol->identifier 'match))
-1))
(namespace-require '(for-template racket/match))
#`(#,x '(1 2 3)
[_ 'yay]))

Actually…never mind.

Because the identifier is still bound there: (identifier-binding #’match)

That is, if I do: (my-m)
(identifier-binding #'match)
under that, I get the binding to racket/match

Oh, also doing the (namespace-require '(for-template racket/match))
only works in the terminal, not drracket. That’s odd…

Ok, re-expansion (as in DrRacket) won’t work, because the macro side-effect won’t happen for the re-expansion. I guess you get the idea, anyway.

Ah, okay.

So probably put it in the template and have it do it, or something like that.

Anyway, thanks.

@leif @mflatt I’m probably missing something here, but why doesn’t syntax-local-lift-require do the trick?

@lexi.lambda Because I…err…didn’t know of its existence. :slightly_smiling_face:

Thanks for pointing it out to me. :heart:

@marioepugh has joined the channel

@leif I think #%namespaced
from that old PR of mine basically does this for you https://github.com/lexi-lambda/racket/blob/0ef4118f876eb2d565be7d5345690e789ab698b1/racket/collects/racket/private/namespaced-transformer.rkt

Oh cool, thanks.

Sadly, when I use take syntax-local-lift-require
out of the toy example and put it in my actual project, I get an ambiguous binding error: editest.rkt:3:22: vertical-block$:elaborate: identifier's binding is ambiguous
context...:
#(78302 module) #(78303 module editest 0) #(78313 macro) #(78316 local)
#(78317 intdef)
matching binding...:
#<module-path-index:(editor)>
#(78302 module) #(78303 module editest 0)
matching binding...:
#<module-path-index:(editor/stdlib)>
#(78303 module editest 0) #(78313 macro)
in: vertical-block$:elaborate
context...:
standard-module-name-resolver

So now I get to detangle that.

Anyway, thanks @lexi.lambda

I’d try and make sure you’re using syntax-local-introduce
appropriately and stripping all the other scopes.

Can someone help me with this, I am struggling.

We are asked to help out with a new software for manipulating images. The team needs us to write a function that will detect if an image is larger than some other image. An image is larger than another image when both the width and height of the first image is larger than the width and height of the second image.
Design a function called image>? that consumes two images and returns #true when the height and width of the first image is larger than the height and width of the second image.

I am attempting to learn racket and trying to write this code but cant grasp it. Any help would be awesome. Thanks

@lexi.lambda syntax-local-introduce
didn’t work, but: (datum->syntax #f (syntax->datum #'modname))
did.

I’m sure there’s a better way to strip away other lexical information though. :slightly_smiling_face:

Anyway, thanks again.

@leif yes, that’s what I mean by “stripping the other scopes”

but I think you probably want to do that plus syntax-local-introduce

(that is, call syntax-local-introduce
on the result of the call to syntax-local-lift-require
to avoid the macro-introduction scope)

but that’s maybe not really necessary

Oh, interesting…

Well I’ll keep that in mind.

I honestly haven’t been able to find a good intuition as to when I need syntax-local-introduce
and when I don’t.

The #%namespaced
form uses a function that strips the lexical information but preserves source locations: https://github.com/lexi-lambda/racket/blob/0ef4118f876eb2d565be7d5345690e789ab698b1/racket/collects/racket/private/namespaced-transformer.rkt#L9-L23

(And when I do but the error is not immediately obvious…)

I only understood syntax-local-introduce
after I learned about the sets-of-scopes expander.

That makes sense.

I don’t care about source locations in this instance, but thanks. :slightly_smiling_face:

(I don’t care because no user will ever see them. :wink: )

I mean, I know what syntax-local-introduce
does.

It makes perfect sense what it does.

@marioepugh That sounds like homework, so we will probably not answer directly, but we might be able to help if you describe specifically what you are confused about.

I just haven’t been able to get a good intuition of when I need to use it, you know?

It’s definitely subtle. But I know too much now, and I can’t remember not knowing it.

The main instances in which I get confused about syntax-local-introduce
these days are when certain functions implicitly apply syntax-local-introduce
in ways that don’t seem well-documented.

Ya, that makes sense.

Also, I tend to agree with @michael.ballantyne that ideally syntax-local-introduce
should be an internal detail.

It just…can’t…because its hard to create the theory for it.

(Given how powerful racket’s macro system is.)

I think Racket’s macro system suffers a little bit from a variety of functions that try to have a “do what I mean” feel to them, which works okay for simple macros, but you need to understand what’s going on under the covers to do really weird things, and the implicit behavior makes it harder to reason about.

Like how identifier-binding
implicitly shifts the phase, as you bumped into earlier.

But sure, how did you get a good intuition for when you need it?

Like, I get when you need to use custom syntax introducers, as well as custom syntax delta introducers.

Its just specifically flipping the macro scope. :wink:

@lexi.lambda Oh yes, I absolutely agree.

Right. And I’m not sure there is more to it than that, in isolation. I guess the hard part is learning when you need/want the macro scope and when you don’t?

There is so many useful things that are just…weird.

And either they’re not documented, or they are, but its a wall of technical details.

mmm…good point.

Well in that case I have that.

I just guess I don’t find it satisfying. Oh well.¯_(ツ)_/¯

The name of syntax-local-introduce
is sort of indicative of this DWIM intent, I think… the name is not “syntax-local-flip-macro-introduction-scope
” because, in simple situations, you use syntax-local-introduce
to really introduce a binding into the surrounding scope? So it’s named in such a way that the scope-flipping is supposed to be an implementation detail.

Ehh…

But I never managed to build an intuition for it until I understood what it actually did (i.e. flipped the scope), so I don’t think that abstraction is very watertight.

But even in simple case, its better to use #:with …

#:with
doesn’t adjust scopes at all, though? I don’t follow… what is the relationship?

I mean, for introducing new piece of syntax.

a new piece of syntax.

Which is why syntax-local-introduce is kind of…an odd name choice.

But ya, syntax-local-flip-the…. is ..well…ya.

Well, syntax-local-introduce
is about introducing a binding into the enclosing, relative-phase–0 scope. #:with
is just about binding a pattern variable for use in phase 1 macro code. So I don’t think there’s much of a conflict/ambiguity there?

There isn’t.

I guess what I’m saying is that Racket tries to be a declarative macro system in the spirit of the original syntax-rules, and it is pretty good at that for a lot of simple things, but I think the abstraction totally breaks down once you start doing slightly nontrivial hygiene bending.

Which isn’t necessarily bad? It’s just an observation.

But its a common pattern to use with combined with format-id to break hygiene. Which in my monkey brain sounds like introducing new syntax.

I’m not saying theirs a conflict, just an unfortunate name choice that fucks with my personal intuition. :wink:

Right… the subtlety there is that format-id
copies the lexical context from another piece of syntax, and that syntax already has the macro-introduction scope. :upside_down_face:

Yup

exactly

Still….you can’t ‘choose’ what fucks with your brain sadly. :disappointed:

And ya, I am okay with it being mostly declarative, but the current implementation leads to some leaky cases that causes programmers in other languages to shy away from it.

Definitely! I think the general failure to properly develop any book or documentation that introduces the low-level macro programming facilities gives at least some reason to think that maybe it’s just too complicated (though a simple lack of time is a big part of that problem, too).

I don’t know how to make it better, though. I’m not sure there’s a simpler or more internally-consistent formulation that makes sense?

Maybe.

That is the problem @michael.ballantyne is trying to solve.

Its also what set of scopes tried to solve.

But every solution seems to break down when you get syntax-local-* and local-expand related stuff.

(Every solution that I’m aware of anyone trying.)

I’m still keeping my fingers crossed that there is actually a nice clean mathematical model.

I know some of @michael.ballantyne’s thoughts, though I do personally find sets-of-scopes relatively easy to understand, probably with the exception of inside/outside-edge scopes (which I know are one of Michael’s pet peeves).

It’s just that Racket doesn’t really provide a direct interface to sets-of-scopes. Or, well… it does, but the names are all different! And different functions implicitly do all sorts of different things based on different edge cases and circumstances.

Oh yes

I absolutely agree.

Compared to the mark/anti-mark model, scope sets are a godsend.

I just don’t think its simple enough. :slightly_smiling_face:

Hmm..

Interesting.

I wonder what it would be like to use a macro system that is still scope sets, but tried, as a principle, to avoid having special cases.

Like, would it be nice to program in.

Right. Do you think understanding procedural macros would be easier or harder if we had functions like make-fresh-scope
instead of make-syntax-introducer
, identifier-bindings=?
instead of free-identifier=?
, and identifier-scopes=?
instead of bound-identifier=?
? I don’t know. Maybe it’d be a lateral move.

And don’t get me started on syntax-local-identifier-as-binding
. :)

lol…

I 100% think it would be easier for crazy stuff.

I just don’t know about simple stuff.

And its not really a system where you can have a ‘simpler’ api and a ‘complex’ api.

That’s my feeling, too. Maybe it doesn’t make sense for them to share the same names, or even the same set of functions.

Because that would be worse.

I think it’s not impossible to have a low-level and high-level API. We already have syntax/parse ways of doing things that are different from older approaches.

True.

Although to be fair, the current way our docs introduce macros to new people is kind of…bleh? you know?

Like, they introduce simple syntax-rules like macros, and then sort of jump in at the deep end.

I really prefer @greg’s approach in fear of macros.

Where he gives you a simple understanding of the model.

Which you can then build on.

So, like, if we were to do that, I would (ideally) want the simple api to grow into the complex api.

So that new programmers have a path for how to do progressively more crazy things.

I think it’s hard to have a one-size-fits all approach to teaching macros, since for many people, syntax-rules
(or define-simple-macro
, as the case may be) is enough.

Yup

I never said it was easy.

It might even be impossible.

Still, its a thing that I strive for…at least ideally.

I’d also like a solution to the halting problem and a unicorn. :slightly_smiling_face:

Anyone know how to go from “an identifier exported by Typed Racket” to “the identifier that the programmer defined, before Typed Racket created a new identifier to protect the export” ?

This github comment has some more details: https://github.com/racket/typed-racket/pull/422#issuecomment-358862732

@ben Dang, before I finished reading your question, my instinct was to respond with “I think there’s an unsafe-reprovide
form or something that does that”. :)