[plt-scheme] Struggling with macro...

From: Ryan Culpepper (ryanc at ccs.neu.edu)
Date: Wed May 23 12:05:24 EDT 2007

On May 23, 2007, at 11:22 AM, Paulo J. Matos wrote:

> On 5/23/07, Jos K oot <jos.koot at telefonica.net> wrote:
>> Hi,
>> Your original question was
>>
>> ;(machine hello ;       (variables (x 1)
>> ;                         (y 2)
>> ;                         (z 3)))
>> ;
>> ;to
>> ;(let ([mc (make-mc () () () () ())])
>> ;     (add-variable-to-mc x 1)
>> ;     (add-variable-to-mc z 3)
>> ;     mc)
>>
>> (BTW, the name 'hello' is not used and I guess that 
>> (add-variable-to-mc x 1)
>> must be (add-variable-to-mc mc x 1))
>>
>
> You're right, name will be used... :) This is just the first part of
> the macro. and yes, mc was missing in that call to add-variable-to-mc.
>
>> For this I would write:
>>
>> (define-syntax machine
>> (syntax-rules (variables)
>>  ((machine name (variables (id v)) ...)
>>   (let ((mc (make-mc () () () () ())))
>>    (add-variable-to-mc mc id v) ...
>>    mc))))
>>
>
> Yes, I understand, still it would not allow multiple (id v). Even if
> you somehow do that with this framework it would not help me.
>
> I will have in the end something like:
> (machine name
>   (variables (var val) ...)
>   (event name ... ) ...
>   )
>
> I want to be able to create the code associated with (variables ...)
> and (event ...) inside an environment where mc is defined so I have
> there the initial let.

You could always pass 'mc' as an argument to the helper macro. See 
below.

> Then I define another macro inside to parse variables, events (only
> variables now, I'm ignoring events) which has mc in scope but things
> are definitely getting trickier. Defining everything in one go as you
> did is not good because I want to have patterns for variables, events,
> etc where order doesn't matter.
>
> I currently have:
> (define-syntax (machine stx)
>    (syntax-case stx ()
>      [(_ mname sexps ...)
>       (identifier? #'mname) ; fender
>       #'(let ([mc (make-mc () () () () ())])
>           (letrec-syntax ((defs (λ (x)
>                                   (syntax-case x (variables)
>                                     [(variables (name value) (... ...))
>                                      (andmap identifier #'name (... 
> ...))
>                                      (begin
>                                        (add-variable-to-mc #'mc
> #'name #'value) (... ...))]))))
>               (defs sexps) ...
>               mc))]))
>
> which, grrrr, is not working. Again, due to name inside the defs macro
> (which seems to be expanding only when machine is called and I
> understand why). I'm getting:
> syntax: missing ellipses with pattern variable in template in: name

There are several problems with this definition.

First, you have
   (andmap identifier #'name (... ...))

The ellipses need to be inside of the #' form, and you need to turn the 
resulting syntax object into a list before you pass it to 'andmap'. And 
'identifier?' needs the '?' at the end. Here's the fix:
   (andmap identifier? (syntax->list #'(name (... ...))))

That will make your macro well-formed. Let's test it on the example you 
gave earlier:

(machine hello
   (variables (x 1) (y 2) (z 3)))

That causes a new error: bad syntax in: (defs (variables (x 1) (y 2) (z 
3))). Why? Look at the pattern for 'defs', and you'll see that you 
aren't matching against the entire macro use, just the argument you 
expect to get. Instead of this pattern:
   (variables (name value) (... ...))
you should have this:
   (defs (variables (name value) (... ...)))

Instead of having the macro produce another macro using 
'letrec-syntax', though, it would be far simpler to lift that macro out 
to a separate definition. You just need to make 'mc' an argument.

Here's how that would look:

(define-syntax (machine stx)
    (syntax-case stx ()
      [(_ mname sexps ...)
       (identifier? #'mname) ; fender
       #'(let ([mc (make-mc () () () () ())])
           (defs-with-mc mc sexps) ...
           mc)]))

(define-syntax (defs-with-mc x)
   (syntax-case x (variables)
     [(defs-with-mc mc (variables (name value) ...))
      (andmap identifier? (syntax->list #'(name ...)))
      #'(begin
          (add-variable-to-mc mc name value) ...)]))

Since you are no longer producing a macro definition, all of the (... 
...) ellipsis-escaping goes away.

You probably ought to quote the variable names before you pass them to 
'add-variable-to-mc',  unless that's also a macro.

Ryan


>
> :( Any ideas?
>
>
>
>> I probably dont grasp your problem. Can you be more specific?
>> Jos Koot
>>
>
>
>
> -- 
> Paulo Jorge Matos - pocm at soton.ac.uk
> http://www.personal.soton.ac.uk/pocm
> PhD Student @ ECS
> University of Southampton, UK
> _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme



Posted on the users mailing list.