
A definition context immediately nested in another can do this when the inner one wants to splice into the outer one. I don’t remember a macro like that offhand to demonstrate, though.

Is there any way to print out the set of scopes associated with an identifier?

(I can’t use the macro stepper because the generated code is too big, so I’m trying to do a bit of print line debugging.)

I suspect @michael.ballantyne or @ryanc might know?

@leif use syntax-debug-info
, or try the debug-scopes
package

I’ve used this scope->symbol
function (with syntax-debug-info
) for debugging, to turn scopes and their jumbles of numbers into letters: https://gist.github.com/AlexKnauth/11cde092aec836aecb21c9634fedd4f3

@ryanc THanks

@mbutterick yes

@mbutterick Nope

Only the first, er, 256[? or was it higher?] characters are represented as immediate values.

Oh, I should mention that I’m referring to classic Racket. Not sure how chars are represented in Chez.

Oh, sorry

Wow — I missed the important part of what you wrote

Yes, the integer values are fixnums.

would adding fixnum-max-value
and fixnum-min-value
to racket be a good idea?

(And the first 256 aren’t represented as immediates; they’re just interned, so they’re pointers, but they’re always the same pointer.)

I think characters are all immediate in Chez.

Is there a way to force module instantiation. I.e., make dynamic-require
twice possible?

What I want to do is to run the same program with different (current-compile)
.

If you want to recompile the module then you need to do more than just reinstantiate. Can you do it in two separate namespaces?

Even doing it in separate namespaces might not be enough, no? You would also need to do something like set use-compiled-file-paths
to empty to avoid current-load/use-compiled
from grabbing the file off disk

Well, if the file isn’t compiled on disk then loading it would compile it in-memory, right? So it could work if the namespaces were different. Or does Racket cache that somehow?

I was assuming it might have been compiled to disk

Yes, in that case you’d also probably want custom-load.

oh right, you don’t want to recompile the universe

@sorawee This might do what you want:
(require custom-load
syntax/modresolve)
(define (path->regexp s)
(regexp (regexp-quote (path->string s))))
(define (force-recompile-for-effect mod)
(parameterize ([current-namespace (make-base-namespace)]
[current-load/use-compiled
(make-custom-load/use-compiled
#:blacklist
(let ([p (resolved-module-path-name
((current-module-name-resolver)
(resolve-module-path mod)
#f
#f
#f))])
(cond [(path? p) (path->regexp p)]
[(pair? p)
(if (path? (first p))
(path->regexp (first p))
empty)]
[else empty])))])
(dynamic-require mod #f)))
depending if you only want to recompile for effect or not

(well, if you want to do this to something in racket/base it wont work, but fixing that just requires some plumbing)

Thanks! I was playing around with your earlier suggestion and the program seems to get stuck at (use-compiled-file-paths '())
. Will try your code right now.

custom-load
isn’t in the main distribution i think, you’ll need to install it

(the pkg has the same name as the collection)

(use-compiled-file-paths '())
will compile the entire racket (except the VM) from source :wink:

Yes

I don’t know. I remember reading through the fixnum docs and not finding any clear answers on what the max and min were, then later I found the (system-type 'word)
trick. But that’s not mentioned anywhere in the fixnum docs.

The main thing is that I want something that’s documented right next to all the other fixnum operations, so if the representation of fixnums changes for some reason (like say, as some consequence of moving to Chez Scheme) there’s no chance of breaking client code that needs to know the max and min fixnums.

It seems entirely possible to me that racket implementation changes could change how the max and min fixnums depend on (system-type 'word)
.

Oh…. interesting.

Yeah that seems like a sensible assumption to me. I just don’t want to have to make such an assumption. It seems way simpler to me to just leave it up to the fixnum module to define what the max and min fixnums are.

The “Not My Job” solution.

I’ve wished I could give a debugging name argument to make-syntax-introducer
like the way module scopes are printed.

@ryanc, @mflatt, & @michael.ballantyne I have the following macro that gives an unbound variable error: https://gist.github.com/LeifAndersen/0e625b56167bbd15a9dfd2745836ae73


Basically, module A
creates a define-foo
, form that creates two macros and has one call another.

(Which is kind of silly in this example, but my actual code base needs to do this for other reasons.)

Anyway, module B
creates its own define/leif
, and uses it plus the define-foo
to make a referencer macro.

Finally, module C
Uses the two form (define/leif)
and the result from define-foo
, but gets an unbound variable.

I feel like there’s something silly I’m missing here, but I can’t seem to get the example any smaller than that. Would you have any idea what’s causing the unbound identifier error?

I’ve wanted these constants, and hard-coded them (or what I think they are) into a program, for purposes like working with bitmasks. I would also like constants for the fixnum limits on the platform with the smallest limits. I think Typed Racket must include some version of those for the Fixnum
and Index
types (“the sets of values included in the types are architecture-dependent, but typechecking is architecture-independent”), but I’m not even sure what predicate corresponds to Index
: https://docs.racket-lang.org/ts-reference/type-ref.html#%28form._%28%28lib._typed-racket%2Fbase-env%2Fbase-types..rkt%29._.Index%29%29

When I run raco setup
on a sub-collection, does it compile the sub-collection’s “main” module, too? For example, given the hierarchy: fruit/
├── apple.rkt
├── apple/
│ ├── granny-smith.rkt
│ └── ...
├── peach.rkt
└── peach/
├── georgia.rkt
└── ...
does raco setup fruit/apple
compile fruit/apple.rkt
, or only fruit/apple/granny-smith.rkt
and its siblings?

@leif The code you’ve written is very twisty, but it seems like maybe you wanted this: #lang racket/base
(module A racket
(require syntax/parse/define)
(provide define-foo)
(define-syntax-parser define-foo
[(_ name body ...)
#:with this-syntax-id (datum->syntax #'name 'this-syntax #'here)
#'(begin
(define-syntax foo2
(syntax-parser
[(_ n)
#:do [(define this-syntax-id #'n)]
body ...]))
(define-syntax name
(syntax-parser
[(_) #`(foo2 #,this-syntax)])))]))
(module B racket
(require (submod ".." A) syntax/parse/define)
(provide (all-defined-out))
(define-syntax-parser define/leif
[(_)
#:with leif (datum->syntax this-syntax 'leif #'here)
#'(define leif 42)])
(define-foo blue
#:with leif (datum->syntax this-syntax 'leif #'here)
#'leif))
(module C racket
(require (submod ".." B))
(define/leif)
(blue))
(require 'C)

The differences are all in module A
: instead of using #'name
as this-syntax
inside foo2
, it uses the original input syntax to name
.

I don’t know, but lately I’ve been avoiding this kind of problem by putting all my code in a private/
directory and only writing #lang reprovide
modules to expose the public collection-ized API


However, there’s a better way. Don’t unhygienically shadow this-syntax
. Instead, call syntax-parse
again inside of foo2
, like this: (module A racket
(require syntax/parse/define)
(provide define-foo)
(define-syntax-parser define-foo
[(_ name body ...)
#'(begin
(define-syntax foo2
(syntax-parser
[(_ orig-stx)
(syntax-parse #'orig-stx
[_
body ...])]))
(define-syntax name
(syntax-parser
[(_) #`(foo2 #,this-syntax)])))]))

@lexi.lambda ya…it is very twisty. Sorry. All of the versions without the twists didn’t give me the unbound identifier error.

That way the this-syntax
syntax parameter will just have the right value, and user code that shadows it will do the right thing.

It does look like you made some changes in B
. but still using the name this-syntax
, yes?

Oh, I just put those uses of #'here
in B
so that the ambiguous binding error would point somewhere useful.

OH, okay

That’s actually very cute. Thanks for pointing it out. :smile:

What you were doing before was copying the lexical context from (the literal identifier) blue
onto the generated leif
identifier.

I think, though, that fruit/apple.rkt
would still need to be re-compiled when fruit/apple/granny-smith.rkt
changes, to avoid errors like “bad variable linkage; reference to a variable that has the wrong procedure or structure-type shape.”

Anyway, I need to shadow this-syntax
sadly.

Because I want this-syntax
to be in scope inside of a define-foo
.

Yes. My only approach to avoid that is to always run raco setup -p mywholepackage

But because its made with a macro plugging into another macro, the default this-syntax
is the outer macro, rather than the original call site.

(I think)

this-syntax
is a syntax parameter, so if you change its value by wrapping something in syntax-parse
, any uses lexically inside the syntax-parse
will use the new value.

OH

I see.

You literally meant introduce a new syntax-parser inside of the syntax-parser.

Syntax parameters are designed precisely to avoid needing to shadow identifiers in that way. The original paper explains them in a little more detail: http://scheme2011.ucombinator.org/papers/Barzilay2011.pdf

And yes, the second example code I gave does just that.

(which is of course inside of yet another syntax-parser
. ;)

Okay though, that’s useful. (I didn’t realize that this-syntax
was a syntax-parameter. I must’ve missed it in the docs.)

It has to be a syntax parameter, not an unhygienically-introduced binding, because it has a binding.

If it were unhygienically introduced, then this-syntax
wouldn’t even be bound outside of syntax-parse
, and the scribble docs wouldn’t be able to link to it or even associate documentation with it (since there would be no binding to attach the documentation to).

That is presuming though that the this-syntax in the docs is the same one from syntax-parse. :wink:

But I get what you mean, and totally agree.

That is what I usually do now, but I often have a sub-collection like example/common
that is used by both example/foo
and example/bar
. The immaginary example/foo
and example/bar
don’t depend on each other, and they don’t peek inside example/common
: they just (require example/common)
. Having to recompile example/bar
is slow when developing example/common
and example/foo
.

how slow?

I haven’t timed it, but the full collection I’m thinking of when I say example
is something like 40,000 lines of code.

In reality, ricoeur/portal
also includes a lot of #lang web-server
code, and the relative slowness of the #lang web-server
compiler is noticeable.

I’ve definitely hit similar issues in my workflow, and I don’t really have any solutions

the compilation infrastructure for racket is frustrating when it comes to dependency management

@lexi.lambda Oh fun, when I made the inner syntax-parse
, I got this error:

define-values: not allowed in an expression position
after encountering unbound identifiers (which is possibly the real problem):
this
define-elaborate
super-new
base$
foo$
define-editor

It looks like somehow those aforementioned identifiers are ending up in a scope where they aren’t bound. But I can’t really say any more without seeing the code.

Ya, that makes sense.

While I’d be happy to share the code with you, your eyes would start bleeding.

(its about 200 lines long, uses splicing-let and splicing-let-syntax, creates submodule pieces (that another macro combines), it creates whole submodules in those submodule pieces. It defines a macro definer, and finally it defines a class type.)

The sad thing is that most of the real smarts are in other macros…the 200 lines is after I factored out a bunch of code. :confused:

(I’m sure there’s more I could factor out obviously.)

Of course though, I’d be happy to point you to it should you decide you’re life needed more unpleasantness in it. :wink:

To be more accurate, the use-compiled-file-paths
parameter instructs where should Racket look for bytecode files.
If it is set to '()
, IIUC any new module declaration will need to load (and compile) from source.
Therefore if you dynamically require racket/contract
in a namespace from (make-base-namespace)
, anything outside racket/base
that racket/contract
depends on will be compiled from source.

Is there any guarantee that two gensym
s will have distinct symbolic names if they were generated in the same namespace? And if not, does anything in Racket marshallable to bytecode provide that kind of guarantee?