Ok, now I am confused, which is not a surprise, really.<br><br>As far as I understand this - the problem is that when specifying<br>yield in the original gets 'renamed' if the macro is used in other<br>macros due to hygiene rules.
<br><br>Ryan's suggestion is to use syntax-parameter, which is a annotation <br>living in the syntax environment only, so it is not altered<br>by the hygiene rules. What is the utility of a syntax-parameter?<br>A syntax variable?
<br><br>Matthias's solution is to augment the body0 syntax-object with the yield binding<br>not the name. Since name might be a used in other contexts, so the resulting yield<br>is identified to be used in the precisely right context. Hygiene rules won't do
<br>the wrong renames/tagging.<br><br>So you could define a kind of a rule of thumb - use the inner most possible <br>scope to introduce new identifiers.<br><br>Cheers,<br>Vlado<br><br><div><span class="gmail_quote">On 8/4/07,
<b class="gmail_sendername">Matthias Felleisen</b> <<a href="mailto:matthias@ccs.neu.edu">matthias@ccs.neu.edu</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Vlado, you can, however, choose a different piece of context syntax<br>for the introduction of the yield binding, namely, one from the<br>scope you really want:<br><br> (define-syntax (define/y stx)<br> (syntax-case stx ()
<br> [(_ (name arg ...) body0 body ...)<br> (with-syntax ((yield-name (datum->syntax-object #;stx (syntax<br>body0) 'yield)))<br> (syntax<br> (define (name arg ...)<br> (define (yield-name x)
<br> (control resume-here<br> (set! name<br> (lambda ()<br> (prompt (resume-here 'dummy))))<br> x))<br> (prompt body0 body ...))))]))
<br><br>If you now target this mini-language with a macro, the non-hygienic<br>binding is introduced properly, e.g.,<br><br> (define-syntax foo<br> (syntax-rules ()<br> ((_ (name arg ...) body ...) (define/y (name arg ...) body ...))))
<br><br> (foo (bar) (printf "hello world\n") (yield 1) (yield 2) 'finished)<br><br> (list (bar) (bar) (bar) (bar))<br><br>-- Matthias<br><br><br><br><br><br><br>On Aug 4, 2007, at 10:58 AM, Ryan Culpepper wrote:
<br><br>> On Fri, 2007-08-03 at 13:35 +0100, Vladimir Zlatanov wrote:<br>>><br>>> 2. How can I use the macro system to eliminate the<br>>> 'yield-name' part<br>>> of the macro?
<br>>><br>>> One solution that works, but I do have a few problems with it.<br>>> I had to break the hygiene, which in this case might not be that bad,<br>>> but it is not nice. More worringly for me, I'm not sure why does it
<br>>> really work the way it works. It is a problem with my<br>>> understanding of<br>>> macros, but that might pass with time =)<br>>><br>>> What would be a hygienic solution?<br>><br>> One problem with using 'datum->syntax-object' to introduce identifiers
<br>> (breaking hygiene) is that it often breaks down when you write another<br>> macro that expands into the first one.<br>><br>> For example, here's a trivial macro:<br>><br>> (define-syntax define-gen
<br>> (syntax-rules ()<br>> [(define-gen (name . args) . body)<br>> (make-gen (name . args) . body)]))<br>><br>> Then use it:<br>><br>> (define-gen (make-step)<br>> (yield 1)<br>> (yield 2)
<br>> (yield 3)<br>> 'finished)<br>> (define step (make-step))<br>> (step) ;; produces error: undefined identifier 'yield'<br>><br>> Why? The 'make-gen' identifier produced by 'define-gen' had a mark on
<br>> it, so the introduced 'yield' identifier had a mark on it, so it<br>> didn't<br>> bind the original, unmarked occurrences of 'yield'.<br>><br>> One nice way to solve this problem is to use syntax parameters. There
<br>> was a thread on this list about them about a year ago, and I wrote<br>> up a<br>> summary here:<br>><br>> <a href="http://macrologist.blogspot.com/2006/04/macros-parameters-binding-">http://macrologist.blogspot.com/2006/04/macros-parameters-binding-
</a><br>> and.html<br>><br>> There's more information in the Help Desk: search for<br>> 'syntax-parameterize'.<br>><br>> Ryan<br>><br>><br>>><br>>> ===========================
<br>>> (require (lib "control.ss"))<br>>><br>>> (define-syntax (make-gen stx)<br>>> (syntax-case stx ()<br>>> [(mkg (name arg ...) body ...)<br>>> (syntax-case (datum->syntax-object (syntax mkg) 'yield) ()
<br>>> [yield (syntax<br>>> (define (name arg ...)<br>>> (define (control-state) body ...)<br>>> (define (yield value) (control resume-here (set!
<br>>> control-state resume-here) value))<br>>> (lambda () (prompt (control-state)))))])]))<br>>><br>>> (make-gen (make-step)<br>>> (yield 1)<br>>> (yield 2)
<br>>> (yield 3)<br>>> 'finished)<br>>><br>>> (define step (make-step))<br>>><br>>> (step)(step)(step)(step)(step)<br>>><br>>> ===========================
<br>>><br>>> _________________________________________________<br>>> For list-related administrative tasks:<br>>> <a href="http://list.cs.brown.edu/mailman/listinfo/plt-scheme">http://list.cs.brown.edu/mailman/listinfo/plt-scheme
</a><br>><br>> _________________________________________________<br>> For list-related administrative tasks:<br>> <a href="http://list.cs.brown.edu/mailman/listinfo/plt-scheme">http://list.cs.brown.edu/mailman/listinfo/plt-scheme
</a><br><br></blockquote></div><br>