[plt-scheme] macro writing

From: Ryan Culpepper (ryan_sml at yahoo.com)
Date: Tue Jun 20 08:55:49 EDT 2006

--- Ivanyi Peter <pivanyi at freemail.hu> wrote:
> 
> > 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.
> 
> Hi,
> 
> Ok, I have done the following. It works, but I am looking for
> some suggestions how to simplify it? My problem is with the
> get-local-init function. I would like to replace it with a
> map but DrScheme always reports an error that I am supplying
> a syntax and not a list. Any idea how to avoid this problem?

You can "unwrap" a syntax object that contains a list one level with
the syntax->list procedure.

In your case, you can also get what you want automatically in the
template of the macro's main syntax-case. Instead of

  (syntax (define (n1 new-args ...)
            (let* (new-locals ...)
              e1 e2 ...)))

write

  (syntax (define (n1 new-args ...)
            (let* ([new-local-var #f] ...)
              e1 e2 ...)))

> Another question: When I expand it to check I get the
> following error:
> 
> > (expand-once (defun a1 () (+ 1 2)))
> define: not allowed in an expression context in: 
> (define (a1) (let* () (+ 1 2)))

You forgot to quote or syntax-quote the thing you were expanding. Try
this:

  (expand-once #'(defun a1 () (+ 1 2)))

Writing #'X is the same as (syntax X).

> So I get the right expansion, but reports the error.
> 
> Thanks for any help,
> 
> Peter
> 
> P.S: Here is the code. (The per sign (/) separates arguments
> and local variables.)

One last note: your code formatting makes this hard to read and
wastes a lot of space. Keep the closing parenthesis on the same line.

Ryan

---------------------------------------------------------------------------------
> 
> (define-syntax defun
>   (letrec
>       ((get-args
>         (lambda (args)
>           (syntax-case args (/)
>             (() (syntax ()))
>             ((/ a1 ...) (syntax ()))
>             ((a2 a3 ...) (cons (syntax a2) (get-args (syntax
> (a3 ...)))))
>           )
>         )
>        )
>        (get-local-init
>         (lambda (args)
>           (syntax-case args ()
>             (() (syntax ()))
>             ((a2 a3 ...) (cons (list (syntax a2) #f)
> (get-local-init (syntax (a3 ...)))))
>             ((a1 ...) (list (list (syntax (a1 ...)) #f)))
>           )
>         )
>        )
>        (get-locals
>         (lambda (args)
>           (syntax-case args (/)
>             (() (syntax ()))
>             ((/ a1 ...) (get-local-init (syntax (a1 ...))))
>             ((a2 a3 ...) (get-locals (syntax (a3 ...))))
>           )
>         )
>        )
>        
>       )
>       
>     (lambda (x)
>       (syntax-case x ()
>         ((_ n1 (args ...) e1 e2 ...)
>          (with-syntax
>              (((new-args ...) (get-args (syntax (args ...)))))
>            (with-syntax
>                (((new-locals ...) (get-locals (syntax (args
> ...)))))
>              (if (null? (syntax (new-locals ...)))
>                (syntax (define (n1 new-args ...) e1 e2 ...))
>                (syntax (define (n1 new-args ...)
>                          (let* (new-locals ...)
>                          e1 e2 ...)))
>              )
>            )
>          )
>         )
>       )
>     )
>   )
> )
> 
> (defun a1 () (+ 1 2))
> (defun a2 (a) (+ 1 a))
> (defun a3 (a b) (+ a b))
> (defun a4 (a b c) (+ a b c))
> (defun a5 (/) (+ 2 3))
> (defun a6 (/ a) (+ 2 3))
> (defun a7 (/ a b) (+ 2 3))
> (defun a8 (/ a b c) (+ 2 3))
> (defun a9 (a b /) (+ a b))
> (defun aa (a b / c) (+ a b))
> (defun ab (a b / c d) (+ a b))
> (defun ac (a b / c d e) (+ a b))
> 
> _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme



Posted on the users mailing list.