Search code examples
schemelispmit-scheme

What is the difference between the these two scheme macros?


provided using mit-scheme

The only modification is from (cthen (make-syntactic-closure env '(it) (third exp))) to (cthen (third exp))

In brief, what difference does make-syntactic-closure make?

(define-syntax aif
  (sc-macro-transformer
   (lambda (exp env)
     (let ((test (make-syntactic-closure env '(it) (second exp)))
       (cthen (make-syntactic-closure env '(it) (third exp)))
       (celse (if (pair? (cdddr exp))
              (make-syntactic-closure env '(it) (fourth exp))
              #f)))
       `(let ((it ,test))
      (if it ,cthen ,celse))))))


(let ((i 4))
  (aif (memv i '(2 4 6 8))
       (car it)))
(define-syntax aif
  (sc-macro-transformer
   (lambda (exp env)
     (let ((test (make-syntactic-closure env '(it) (second exp)))
           (cthen (third exp))
       (celse (if (pair? (cdddr exp))
              (make-syntactic-closure env '(it) (fourth exp))
              #f)))
       `(let ((it ,test))
      (if it ,cthen ,celse))))))


(let ((i 4))
  (aif (memv i '(2 4 6 8))
       (car it)))

I tried the two version of macro, but got the same result.


Solution

  • A syntactic closure captures the syntactic environment and allows identifiers present in it to be used in the form as variables, instead of having a meaning provided by the environment of the macro transformer (It also lets you specify a list of free names like it in this case that can be set or otherwise used in the macro body and have that binding used in the expanded form; basically it removes those names from the given environment)

    An example:

    (let ((i 4)
          (x '(a b c)))
      (aif (memv i '(2 4 6 8))
           (car x)))
    

    With the first version of your aif macro, this evaluates to 'a. With the second version, it generates an error Unbound variable: x, because in the macro cthen is a list, not a syntactic closure, and x is unbound in the macro transformer so it can't be found when the expanded body is evaluated.