
Yes, that’s was the suggestion. To have it in a module, but not with code, to make it project wide. I have forked it into https://github.com/LinkiTools/syntax-warn and will give a try implementing this.

Wow, what a coincidence - I’ve spent some time lately on almost this exact problem. Even called my implementation “annotations” and used @foo
as a naming convention.

(Java is one helluva drug)

@gregor.kiczales Modules (and internal definition contexts like lambda bodies) are expanded in 2 passes (we use the word phase to mean something else). The first pass uncovers and processes module-level definitions and requires so that at the end of the first pass, the module’s top-level environment is known and fixed. During the first pass, the expander stops whenever it hits an expression. The second pass goes back over the module body and expands the expressions. So to check that something is defined, you want to arrange for the macro that actually does the check to be expanded during pass 2. The easiest way to do that is for your main macro, @HtDF
, to unconditionally expand into uses of a helper macro (let’s call it check-defined-here
) within an #%expression
wrapper. ;; (@HtDF id ...) : module-level-form
;; Raises an error at compile time if any id is not defined somewhere
;; in the current module (as a function?).
;; (@HtDF id ...) => (begin (#%expression (check-defined-here id)) ...)
Then your helper macro can actually do the checking using identifier-binding
or whatever. If you want to be extra cautious, you can have the macro explicitly check its precondition (that it is used in pass 2) by making sure that (syntax-local-context)
returns 'expression
. Likewise, if you want to only allow @HtDF
at module-top-level or (interactive) top-level, you could have it check its (syntax-local-context)
too.

@c25l has joined the channel

@mflatt Can you explain to me why this program fails with an unbound identifier error? #lang racket
(define-syntax (m stx)
(syntax-local-lift-require #'racket/base (datum->syntax #f '(void))))
(m)
void: unbound identifier;
also, no #%app syntax transformer is bound
at: void
in: (void)
context...:
#(2951 macro) #(2953 macro) [common scopes]
other binding...:
#(void #<module-path-index:'#%runtime> 0)
#(9 module) #(2953 macro) [common scopes]
other binding...:
#(void #<module-path-index:'#%runtime> 0)
#(9 module) [common scopes]
common scopes...:
#(2320 module lift-require)
It seems like the identifier is missing the #(9 module)
scope, but I don’t have an intuition for what exactly that means in this case. Is there a reason syntax-local-lift-require
doesn’t add the module’s scope?

It works fine if I do (syntax-local-lift-require 'racket/base (datum->syntax #f '(void)))
, instead, so I guess it’s just that the lexical context on the require spec is meaningful, which is less interesting than I thought.

It would have taken me a while to figure that out, but I think you’re right.

@tetsumi I remember now why fxvectors and flvectors are not allowed with read-syntax
. It’s because there are currently no immutable variants of those datatypes.

could they expand into something that always dup’s them when used as literals?

@mflatt i see. Aren’t fxvector and normal vector sharing the same C structure (Scheme_Vector)?

@zenspider We don’t currently have a way for read-level things to imply a particular expansion, although we have thought about ways to enable that

@tetsumi It’s not a question of how immutable would be represented, but just adding all the things (new functions and checks on mutating functions) to support immutable values. We can add all that for fxvectors and flvectors if it’s useful, but it seemed too tedious to add absent any demand.

@ryanc Thanks that’s working well now.

what is the point of boxes? theyre kind of explained in PLAI 8.1 Mutable Structures as a way to introduce mutation

but if racket already has mutation

is that just a way to make it obvious ?

oh, should have googled better. this thread kind of explained it to me: https://lists.racket-lang.org/users/archive/2010-October/042446.html

cosmez: I think you can pass boxes around and let others modify the same box there’s no such thing for variables / bindings