[plt-scheme] auxiliary macros

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Sat Aug 4 12:05:58 EDT 2007

Vlado, you can, however, choose a different piece of context syntax
for the introduction of the yield binding, namely, one from the
scope you really want:

  (define-syntax (define/y stx)
   (syntax-case stx ()
     [(_ (name arg ...) body0 body ...)
      (with-syntax ((yield-name (datum->syntax-object #;stx (syntax  
body0) 'yield)))
        (syntax
         (define (name arg ...)
           (define (yield-name x)
             (control resume-here
              (set! name
                    (lambda ()
                      (prompt (resume-here 'dummy))))
              x))
           (prompt body0 body ...))))]))

If you now target this mini-language with a macro, the non-hygienic
binding is introduced properly, e.g.,

   (define-syntax foo
     (syntax-rules ()
      ((_ (name arg ...) body ...) (define/y (name arg ...) body ...))))

   (foo (bar) (printf "hello world\n") (yield 1) (yield 2) 'finished)

   (list (bar) (bar) (bar) (bar))

-- Matthias






On Aug 4, 2007, at 10:58 AM, Ryan Culpepper wrote:

> On Fri, 2007-08-03 at 13:35 +0100, Vladimir Zlatanov wrote:
>>
>>         2. How can I use the macro system to eliminate the
>>         'yield-name' part
>>         of the macro?
>>
>> One solution that works, but I do have a few problems with it.
>> I had to break the hygiene, which in this case might not be that bad,
>> but it is not nice. More worringly for me, I'm not sure why does it
>> really work the way it works. It is a problem with my  
>> understanding of
>> macros, but that might pass with time =)
>>
>> What would be a hygienic solution?
>
> One problem with using 'datum->syntax-object' to introduce identifiers
> (breaking hygiene) is that it often breaks down when you write another
> macro that expands into the first one.
>
> For example, here's a trivial macro:
>
> (define-syntax define-gen
>   (syntax-rules ()
>     [(define-gen (name . args) . body)
>      (make-gen (name . args) . body)]))
>
> Then use it:
>
> (define-gen (make-step)
>   (yield 1)
>   (yield 2)
>   (yield 3)
>   'finished)
> (define step (make-step))
> (step) ;;  produces error: undefined identifier 'yield'
>
> Why? The 'make-gen' identifier produced by 'define-gen' had a mark on
> it, so the introduced 'yield' identifier had a mark on it, so it  
> didn't
> bind the original, unmarked occurrences of 'yield'.
>
> One nice way to solve this problem is to use syntax parameters. There
> was a thread on this list about them about a year ago, and I wrote  
> up a
> summary here:
>
> http://macrologist.blogspot.com/2006/04/macros-parameters-binding- 
> and.html
>
> There's more information in the Help Desk: search for
> 'syntax-parameterize'.
>
> Ryan
>
>
>>
>> ===========================
>> (require (lib "control.ss"))
>>
>> (define-syntax (make-gen stx)
>>   (syntax-case stx ()
>>     [(mkg (name arg ...) body ...)
>>      (syntax-case (datum->syntax-object (syntax mkg) 'yield) ()
>>        [yield (syntax
>>                (define (name arg ...)
>>                  (define (control-state) body ...)
>>                  (define (yield value) (control resume-here (set!
>> control-state resume-here) value))
>>                  (lambda () (prompt (control-state)))))])]))
>>
>> (make-gen (make-step)
>>           (yield 1)
>>           (yield 2)
>>           (yield 3)
>>           'finished)
>>
>> (define step (make-step))
>>
>> (step)(step)(step)(step)(step)
>>
>> ===========================
>>
>> _________________________________________________
>>   For list-related administrative tasks:
>>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>
> _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme



Posted on the users mailing list.