[gambit-list] macro-expansion bug (?)

Marc Feeley feeley at IRO.UMontreal.CA
Tue Feb 22 10:34:59 EST 2005


> Hi,
> 
> The following works in chicken and bigloo, but fails on gambit  4.0b12:
> 
> ---------------------------------------------------------------------------------------
> (define-macro (build-funcs)
>   (define any '(list? number? string?))
> 
>   (define funcnames
>     `((is-string string?)
>       (is-number number?)
>       (is-list list?)
>       (is-any ,any)))
>   (define (build desc)
>     (let ((name (car desc))
>           (tests (if (list? (cadr desc))
>                      (cadr desc)
>                      (cdr desc))))
>       `(define ,name
>          (lambda (o)
>            (or ,@(map (lambda (x)
>                         (list x 'o))
>                       tests))))))
>   `(begin ,@(map build funcnames)))
> 
> (pp (lambda () (build-funcs) #t))
> (build-funcs)
> 
> (is-any "dd")
> ---------------------------------------------------------------------------------------
> 
> It seems that the reference to the `any' variable is unbound inside
> `funcnames'.  If you move the definition of `any' outside of the body
> of `build-funcs', everything works fine.
> 
> Not sure if this is a bug, or a misunderstanding on my part.

Your code is not legal R5RS Scheme.  In R5RS Scheme you can't use in
the evaluation of the value part of a "define" a variable "define"d at
the same level.  I.e. this is illegal:

(define (f x)

  (define n 10)
  (define m (+ n 1))

  ...)

You should use let* instead like this:

(define-macro (build-funcs)
  (let* ((any
          '(list? number? string?))
         (funcnames
          `((is-string string?)
            (is-number number?)
            (is-list list?)
            (is-any ,any))))

    (define (build desc)
      (let ((name (car desc))
            (tests (if (list? (cadr desc))
                       (cadr desc)
                       (cdr desc))))
        `(define ,name
           (lambda (o)
             (or ,@(map (lambda (x)
                          (list x 'o))
                        tests))))))

    `(begin ,@(map build funcnames))))

Note that your original code will work in Gambit 3.0, but in version
4.0 the implementation was changed to detect these violations of the
R5RS Scheme standard.

Marc



More information about the Gambit-list mailing list