[plt-scheme] Compile and Run-Time Phase question
At Wed, 21 Jan 2009 14:18:11 -0800 (PST), Adrian Patino wrote:
> (define-syntax identifier-syntax
> (lambda (x)
> (syntax-case x ()
> ((_ e)
> (syntax
> (lambda (x)
> (syntax-case x ()
> (id
> (identifier? (syntax id))
> (syntax e))
> ((id x (... ...))
> (identifier? (syntax id))
> (syntax (e x (... ...)))))))))))
>
> (let ((x 0))
> (define-syntax x++
> (identifier-syntax
> (let ((t x)) (set! x (+ t 1)) t)))
> (let ((a x++))
> (list a x)))
>
> returns with error:
> expand: unbound identifier in module (in the transformer environment,
> which does not include the macro definition that is visible to run-
> time expressions)
>
> using (define-for-syntax identifier-syntax ...) insteads returns with
> error:
> compile: identifier used out of context in: x
> referring to the x in the let expression.
>
> Why is it out of context?
When you use `define-for-syntax', then you bind a function
`identifier-syntax' that can be used directly in an transformer
expression. So, `(identifier-syntax (let ((t x)) ...))' is treated as a
function call, and `x' is treated as a direct reference to the one
bound to 0. A transformer expression cannot refer directly to a
run-time variable (since it doesn't exist, yet), so that's why you get
an out-of-context error.
> Also, I noticed that other scheme implementations allow this code to
> work, such as ypsilon. What are the benefits of using define-for-
> syntax?
`define-for-syntax' is not what you want in this case. It binds a
variable at compile time for use at compile time. You want to bind a
macro at compile time for use at compile time. So, you'd want
`define-syntax-for-syntax' --- which isn't currently supported.
To make this code work in PLT Scheme, you have to put
`identifier-syntax' in a separate module, and then import it
`for-syntax' into the module that uses `identifier-syntax' for a
transformer expression.
Matthew