[racket] Strange macro behavior with set! and syntax-local-introduce

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Thu May 15 19:55:42 EDT 2014

Yes, being forced to use 'stx' as context is suspicious, too. It injects the identifier into the scope and a program may accidentally see it then. 



On May 15, 2014, at 7:20 PM, Robby Findler wrote:

> We have a work around. (In the larger program there is one is that comes from the input and one that doesn't. We can just bind it to a pair instead.)
> 
> This program seems quite suspicious. I can't quite bring myself to call it a bug because it is sucks widely used part of things tho!
> 
> Robby
> 
> On Thursday, May 15, 2014, Matthias Felleisen <matthias at ccs.neu.edu> wrote:
> 
> 
> On May 15, 2014, at 5:56 PM, Robby Findler wrote:
> 
>> How does this help us understand the original, strange program?
> 
> 
> I am providing a work-around because I recognize the idiom. 
> I can't explain the original. 
> 
> 
> 
> On May 15, 2014, at 6:23 PM, Spencer Florence wrote:
> 
>> I'm not sure how gensym fixes this:
> 
> 
> Not #f, stx: 
> 
> (define-syntax (make-funny-set! stx)
>   (syntax-parse stx
>     [(_ v) #`(define #,(begin (set! funny (datum->syntax stx (gensym))) funny) v)]))
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
>> 
>> #lang racket
>> 
>> (require (for-syntax syntax/parse racket/syntax racket/format))
>> 
>> (define-for-syntax funny #f)
>> 
>> (define-syntax (make-funny-set! stx)
>>   (syntax-parse stx
>>     [(_ v) #`(define #,(begin (set! funny (datum->syntax #f (gensym))) funny) v)]))
>> 
>> (define-syntax (funny-ref stx)
>>   (syntax-parse stx
>>     [(_) funny]))
>> 
>> (define-syntax (funny-set! stx)
>>   (syntax-parse stx
>>     [(_ v) #`(set! #,funny v)]))
>> 
>> (make-funny-set! 2)
>> (void (void (void (funny-set! 3))))
>> (funny-ref)
>> 
>> errors with:
>> 
>>   g27591: unbound identifier;
>>    also, no #%top syntax transformer is bound in: g27591
>> 
>> regardless of how many calls to void there are (inclusive of 0). This makes sense, as the syntax marks don't add up. The calls to "syntax-local-introduce" in the original program aught to solve this, but as we saw... `/me points to robby's email`
>> 
>> 
>> 
>> And removing the datum->syntax errors with:
>> 
>>   funny-ref: received value from syntax expander was not syntax
>>     received: 'g27876
>> 
>> Which also makes sense: a symbol is not Syntax.
>> 
>> 
>> 
>> 
>> On Thu, May 15, 2014 at 4:56 PM, Robby Findler <robby at eecs.northwestern.edu> wrote:
>> How does this help us understand the original, strange program?
>> 
>> Robby
>> 
>> On Thu, May 15, 2014 at 4:51 PM, Matthias Felleisen
>> <matthias at ccs.neu.edu> wrote:
>> >
>> > Then use gensym instead of g and "~a" instead.
>> >
>> >
>> >
>> > On May 15, 2014, at 5:38 PM, Matthias Felleisen <matthias at ccs.neu.edu> wrote:
>> >
>> >>
>> >> Did you want this:
>> >>
>> >> #lang racket
>> >>
>> >> (require (for-syntax syntax/parse racket/syntax))
>> >>
>> >> (define-for-syntax funny #f)
>> >>
>> >> (define-syntax (make-funny-set! stx)
>> >>  (syntax-parse stx
>> >>    [(_ v) #`(define #,(begin (set! funny (format-id stx "g")) funny) v)]))
>> >>
>> >> (define-syntax (funny-ref stx)
>> >>  (syntax-parse stx
>> >>    [(_) funny]))
>> >>
>> >> (define-syntax (funny-set! stx)
>> >>  (syntax-parse stx
>> >>    [(_ v) #`(set! #,funny v)]))
>> >>
>> >> (make-funny-set! 2)
>> >> (void (void (void (funny-set! 3))))
>> >> (funny-ref)
>> >>
>> >> [I had to write such a macro a while back, and the above is roughly what I remember doing. Note the lexical context]
>> >>
>> >>
>> >> On May 15, 2014, at 5:25 PM, Spencer Florence <spencer at florence.io> wrote:
>> >>
>> >>> I'm attempting to write a macro which introduces a new id, then another macro that set!s that id.
>> >>> Example:
>> >>>
>> >>> #lang racket
>> >>> (require (for-syntax syntax/parse racket/syntax))
>> >>> (define-for-syntax funny #f)
>> >>> (define-syntax (make-funny-set! stx)
>> >>>  (syntax-parse stx
>> >>>    [(_ v)
>> >>>     (define unmarked (generate-temporary))
>> >>>     (set! funny (syntax-local-introduce unmarked))
>> >>>     #`(define #,unmarked v)]))
>> >>> (define-syntax (funny-ref stx)
>> >>>  (syntax-parse stx
>> >>>    [(_)
>> >>>     funny]))
>> >>> (define-syntax (funny-set! stx)
>> >>>  (syntax-parse stx
>> >>>    [(_ v)
>> >>>     #`(set! #,(syntax-local-introduce funny) v)]))
>> >>>
>> >>> (make-funny-set! 2)
>> >>> (funny-set! 3)
>> >>> (funny-ref)
>> >>>
>> >>> This program works as I expect, evaluating to 3. However if I change (funny-set! 3) to (void (funny-set! 3)) I get the error: "set!: unbound identifier in module in: g1"
>> >>>
>> >>> I do not get this error if I change (funny-ref) to (void (funny-ref)).
>> >>>
>> >>> If I look at the expansion of the (void (funny-set! 3)) program in drracket's macro stepper the the g1 in (define g1 2) and the g1 in (void (set! g1 3)) have the
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140515/be90bdde/attachment-0001.html>

Posted on the users mailing list.