
@ryanc Hi, I sent a pull request to custom-load
. The default use-compiled handler will check the existence of a file, so I added that check

@ashakdwipeea has joined the channel

@mflatt Is there an equivalent to ctype-scheme->c
and ctype-c->scheme
in the ffi lib? I see it in '#%foreign
, but the docs say that it shouldn’t be used directly.

For reference, I’m trying to build my own define-cstruct
macro, because the existing one doesn’t support versions, which I need.

From the second page, I think this covers it: (define-macro-cases bf-op
[(bf-op ">") #'(gt)]
[(bf-op "<") #'(lt)]
[(bf-op "+") #'(plus)]
[(bf-op "-") #'(minus)]
[(bf-op ".") #'(period)]
[(bf-op ",") #'(comma)])
(provide bf-op)

@leif Those are not meant to be exposed, and the way that define-cstruct
uses ctype-scheme->c
and ctype-c->scheme
looks like a hack to me. I recommend using cpointer-push-tag!
for the C->Scheme part, and use cpointer-has-tag?
for the Scheme->C part. The little bit of duplication that you’ll have is better than the hack.

@sanchom A reference to handle
originates in the reader, before identifiers have scope, while references to gt
, etc., originate in expansion. In other words, it’s roughly that handle
is introduced by a '
form, while gt
, etc., are introduced by #'
forms.

Can someone in here explain why we always write the former of these two programs instead of the latter? #lang racket
(require (for-syntax racket/syntax)
syntax/parse/define)
(define-simple-macro (definer1 x:id)
(define-syntax x 42))
(define-simple-macro (consumer1 x:id)
#:with value (syntax-local-value #'x)
(quote value))
(definer1 foo)
(consumer1 foo)
(define-simple-macro (definer2 x:id)
(define-for-syntax x 42))
(define-simple-macro (consumer2 x:id)
#:with value (syntax-local-eval #'x)
(quote value))
(definer2 foo)
(consumer2 foo)
I’ve never fully understood why we use phase 0 transformer bindings to store data that macros have access to instead of just using phase 1 bindings.

@lexi.lambda One possible reason: Since begin-for-syntax
doesn’t work in internal-definition contexts, the latter works only at the module level, while the former also works in local contexts.

Ahh, that makes sense. So you can’t have a notion of nested local scopes from different phases.

That means David’s suggestion to use phases as namespaces unfortunately probably won’t work. Let me ask a followup question, then: is there any way for Racket programmers to inject requires that have the same shadowing behavior as bindings imported by the module language? Alternatively, is there any way to adjust how bindings provided by a module language are imported?

Essentially, I have a require transformer unmangle-types-in
, and I inject it into every require
. That transformer finds all the mangled type imports, unmangles them, and applies the type scope. I can’t do that for types provided by the module language, though, because there are obviously no “module language transformers”.

And if I adjust the reader to transform #lang hackett
into (module m hackett (require hackett))
, then users are unable to shadow bindings provided by hackett
with other require
s.

I think this would be a problem even if I were using something like submodules to store bindings instead of a name mangling scheme, but maybe I’m overlooking something.

How can one write a macro such that it can report the name of procedure which invokes it? I basically want something like:
(define-syntax (foo)
(syntax-parse stx
[(_)
(with-syntax ([invoking-proc (?? get-invoking-proc ??)])
(syntax/loc stx
(begin
(eprintf "foo called from: ~v" invoking-proc)
(void))))]))

What do you mean “the procedure that invokes it”? Isn’t the procedure that invokes macro transformers just the macroexpander? Or do you want to know something about where the macro is used?

The context in which the macro is used. Like if I had (define (my-fn) (foo))
then my-fn
should printf foo called from "my-fn"
as a side effect.

I don’t think you can do that.

You could create your own custom version of define
that set up some lexical information that another macro could use. But I don’t think the built-in define
does anything like that.

I thought the contract system could do things like this? I.e. when a contract is broken, it gives you information about whether the blame lies with the function itself, or the context in which it was called. Either way not a huge deal.

I think the contract system does that with define/contract
, which has syntactic access to the name, but I think it usually only blames modules.

Gotcha, thanks for the info.

@ryanc I take it from the existence of custom-load
that racket
does not by default behave the way @samth describes? Do you know why racket
isn’t more cautious? It seems like the timestamp check shouldn’t be too expensive compared to the rather larger cost of actually loading and instantiating a module.
To be clear, the behavior I’m talking about is the following:
mkdir example; cd example
cat <<EOF >a.rkt
#lang racket
(define x 'old)
(provide x)
EOF
cat <<EOF >b.rkt
#lang racket
(require "a.rkt")
x
EOF
raco make b.rkt
cat <<EOF >a.rkt
#lang racket
(define x 'new)
(provide x)
EOF
# Prints 'old
racket b.rkt
raco make b.rkt
# Prints 'new
racket b.rkt

I think that what’s happening there is that the compiled version of b.rkt
includes the actual symbol

so fixing this requires that b.rkt be recompiled, even though its zo is not out of date

what I said earlier remains correct

@mflatt I’m trying to better understand the syntax model behind (module* m #f ....)
submodules, since the docs seem a little sparse. Does it make sense for splicing-syntax-parameterize
to affect such submodules? If not, why not? Currently, it looks like the implementation of splicing-syntax-parameterize
ignores all module*
submodules, but it would be convenient for me if it were possible to affect them that way (and, since they inherit bindings around them, it seems like it should theoretically be possible).

@lexi.lambda I think it would make sense for splicing-syntax-parameterize
to work with (module* m #f ....)
, but I’ve never tried

There’s no way, as far as I can see, to import in a way that allows shadowing

Okay, that’s probably enough for me to go on… I just have little idea how syntax parameters actually work, so I didn’t want to try something completely wrong. :)

As for imports, I think the namespace issue is surprisingly hard. :( But I think I might be able to get something that almost works, modulo the issue with import shadowing.

$ cat module-begin.rkt
#lang racket
(require syntax/parse/define)
(define-simple-macro (#%module-begin form ...)
#'(#%plain-module-begin form ...))
(module* use #f)
$ racket module-begin.rkt
module-begin.rkt:8:0: module*: compiled body was not built with #%module-begin
in: (module* use #f)
wat

oh, hah—the #'
is wrong there. still have no idea what that error message is about…