chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Chicken-users] A problem with let-syntax?


From: Tomasz Primke
Subject: [Chicken-users] A problem with let-syntax?
Date: Tue, 27 Oct 2009 15:06:15 +0100

I'm working on macros which should define many procedures. My first
try was to write a macro, that after such a call:

(defproc myproc a b c)

would define the following procedures:

myproc-a
myproc-b
myproc-c

The returned values don't matter; it's just an exercise.

Here's my code:

(define-syntax defproc-aux
  (syntax-rules ()
    ( (_ name msg)
      (define (name) (print msg)) )))

(define-syntax defproc
  (lambda (exp ren comp)
    ; The base procedure name string.
    (let* ( (base (cadr exp))
            (baseStr (symbol->string base))
            (params (cddr exp)) )
      ; Extract all the methods and prepare macro forms.
      (let loop ( (params params) (acc '()) )
        (if (null? params)
          `(begin ,@acc)
          (let* ( (methSymb (car params))
                  (methStr (symbol->string methSymb))
                  (methNameStr (string-append baseStr "-" methStr))
                  (methName (string->symbol methNameStr))
                  (newAcc (cons `(defproc-aux ,methName ,methStr) acc)) )
            (loop (cdr params) newAcc)))))))


I started with defproc-aux defined outside the defproc macro, with
define-syntax. This macro worked as expected:

#;> (expand '(defproc myproc a b c))
(begin (defproc-aux myproc-c "c") (defproc-aux myproc-b "b")
  (defproc-aux myproc-a "a"))
#;> (defproc myproc a b c)
#;> myproc-a
#<procedure (myproc-a)>
#;> myproc-b
#<procedure (myproc-b)>
#;> myproc-c
#<procedure (myproc-c)>

So, I thought that I had learnt how to write such macros and tried to
write something very similar:

(define-syntax defproc2
  (lambda (exp ren comp)
    ; The auxiliary macro.
    (let-syntax ( (defproc-aux2 (syntax-rules ()
                                  ( (_ name msg)
                                    (define (name) (print msg)) ))) )
      ; The base procedure name string.
      (let* ( (base (cadr exp))
              (baseStr (symbol->string base))
              (params (cddr exp)) )
        ; Extract all the methods and prepare macro forms.
        (let loop ( (params params) (acc '()) )
          (if (null? params)
            `(begin ,@acc)
            (let* ( (methSymb (car params))
                    (methStr (symbol->string methSymb))
                    (methNameStr (string-append baseStr "-" methStr))
                    (methName (string->symbol methNameStr))
                    (newAcc (cons `(defproc-aux2 ,methName ,methStr) acc)) )
              (loop (cdr params) newAcc))))))))

The reason was simple: I wanted to make it clear, that this auxiliary
macro is needed only in defproc2. Unfortunatelly, it doesn't work at
all:

#;> (expand '(defproc2 myproc a b c))
(begin (defproc-aux2 myproc-c "c") (defproc-aux2 myproc-b "b")
   (defproc-aux2 myproc-a "a"))
#;16> (defproc2 myproc a b c)

Error: unbound variable: defproc-aux2

        Call history:

        <eval>          (##sys#cons (quote553 begin) (##sys#append acc 
(quote553 ())))
        <eval>          (##sys#append acc (quote553 ()))
        <syntax>                (begin (defproc-aux2 myproc-c "c") 
(defproc-aux2 myproc-b
"b") (defproc-aux2 myproc-a "a"))
        <syntax>                (defproc-aux2 myproc-c "c")
        <syntax>                (defproc-aux2 myproc-b "b")
        <syntax>                (##core#begin (defproc-aux2 myproc-a "a"))
        <syntax>                (defproc-aux2 myproc-a "a")
        <eval>          (defproc-aux2 myproc-c "c")     <--

Well, I'm new to Chicken (and to Scheme, although I have some basic
experience already). If I understand these messages, the defproc-aux2
isn't bounded to the macro defined by the let-syntax form.

The question is why?

According to all my knowledge based on R5RS docs and TSPL (3rd and 4th
editions) the let-syntax form should work just as the defproc-aux2 was
defined with define-syntax (in this let-syntax form's scope).

I'm using the Chicken version 4.2.0.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]