[plt-scheme] macro writing
On 6/20/06, Ivanyi Peter <pivanyi at freemail.hu> wrote:
> I would like to do something like this. How can I solve the
> problem
> to have a second ellipses in the list after "locals"? Can
> somebody help
> me with this or point to the right direction?
> (Macro writing is not my strength.)
Let me see if I can help. Obviously you can't do it the way you tried
- syntax-rules doesn't allow anything after the ellipsis (the "...")
in a pattern. So you're going to have to do something else to
separate your arguments from your local definitions.
> (define-syntax call
> (syntax-rules ( locals )
> ((_ n1 (v1 v2 ... locals v3 v4 ...) e1 e2 ...)
> (define (n1 v1 v2 ...)
> (let*
> ((v3 #f) (v4 #f) ...)
> e1 e2 ...
> )))))
>
> (call aa (a b locals c)
> (set! c 3)
> (+ a b c)
> )
I assume you want the above to expand to:
(define (aa a b)
(let* ((c #f))
(set! c 3)
(+ a b c)))
Off the top of my head, I can think of three options for you.
SUGGESTION ONE:
Separate the definitions manually. Match on the following pattern initially:
(syntax-rules ()
((_ n1 (any-names ...) e1 e2 ...)
<code here>))
And in <code here>, write code to manually search through (syntax
(any-names ...)) for the keyword "locals". Then you can construct
separate lists or syntax objects for arguments and local definitions.
SUGGESTION TWO:
Change the pattern. Match on this pattern:
(syntax-rules ()
((_ n1 (v1 v2 ...) (v3 v4 ...) e1 e2 ...)
<code here>))
So your example becomes:
(call aa (a b) (c)
(set! c 3)
(+ a b c))
SUGGESTION THREE:
Write separate macros, one for defining functions with arguments and
one for defining local names. Your example might look like:
(call aa (a b)
(locals (c)
(set! c 3)
(+ a b c)))
Of course at this point, you might as well use "define" instead of
"call"; the only new syntax is "locals" which defines a set of names
and initializes them to #f.
As a separate note, you might also consider initializing locals to the
undefined value using letrec, instead of #f. It might give clearer
error messages (seeing #<undefined> instead of #f tells the user what
went wrong). In the third suggestion, that would look like:
(define-syntax locals
(syntax-rules ()
((_ (name ...) e1 e2 ...)
(letrec ((name name) ...)
e1 e2 ...))))
I hope this was helpful. Let me know if you have questions about any
of my slew of suggestions.
--
Carl Eastlund
"Cynical, but technically correct."