This site is a static rendering of the Trac instance that was used by R7RS-WG1 for its work on R7RS-small (PDF), which was ratified in 2013. For more information, see Home.

Ticket 47: internal define-syntax

2012-10-05 00:37:57
WG1 - Macros
2010-03-22 10:19:44

R6RS extends define-syntax to be allowed in local lexical contexts. Do we allow this as well?

Sounds good to me, on the principle of self-consistency, which the charter says is an important objective.

Why not allowing also nested define-syntax for defining submacros ?

What do you mean by allowing nested define-syntax? Is this different than the internal define-syntax that is permitted by R6RS?

I mean to allow nested define-syntax like we already have for nested define:

(define-syntax foo (define-syntax bar ...) ...)

So that bar could be called from foo as a submacro and be visible only by foo.

This isn't actually allowed for DEFINE either. Something like

(define a (define b 3) b))

Doesn't work. in R6RS, both DEFINE and DEFINE-SYNTAX in their simple forms expect an identifier followed by an expression. In either case, it's trivial to do something like:

(define a (let () (define b 3) b)))

On the other hand, there is the shortcut with DEFINE that lets you put an implicit lambda there. I am not sure that this is as simple a change, as say, #53.

Sure this is not allowed with define and this is because of lambda shortcut for define that we could put sub-definitions.

(define (foo arg ...) <definition>* ...) => (define foo (lambda (arg ...) <definition>* ...))

For syntax-case we have a lambda so there is no problem for nesting. The situation is different with define-syntax and syntax-case (I don't see how to have a similar shortcut). It would be nice to avoid putting a "let ()" for each submacro level defined.

There are many choices, I proposed this one:

(define-syntax foo (define-syntax bar ...)) (syntax-rules () ...))

There is also this style:

(define-syntax foo (syntax-rules () (define-syntax bar ...)) ...))

Among the possible choices I personally prefer the first one as most convenient.

What would make this change more difficult ? One possible implementation would be to flatten internally all macro definition and then to make sure direct calls to submacros make reference to corresponding macros:

(define-syntax <foo~bar> ...)) (define-syntax foo ;; Direct calls to bar replaced by calls to <foo~bar> (syntax-rules () ...))

While this is convenient, if we are going to avoid dealing with arbitrary code in the meta phase in WG1, we have to be careful about such forms, because we're inviting a situation where we have to start being fuzzy. We can't specify that there is an implicit LET-NIL on the right hand side, because that would allow arbitrary code at the meta phase, which immediately brings in phasing issues. While I'm not opposed to this, we have to be aware of the extra work that it causes. I assume that you're talking purely about allowing DEFINE-SYNTAX in there, but then we have to be careful about forwards compatibility with WG2.

In other words, I expect that only a limited subset of the potential functionality will be allowed here, and we have to explicitely leave the rest unspecified, this makes things very fuzzy, and is no where near as easy as just changing BEGINs to LET-NILs.


The WG voted to accept this feature.