1

我在诡计中有宏 let-- (比如 let* 使用 lambdas ):

(define (let-make-lambdas pairs body)
    (if (null? pairs)
        `((lambda () ,@body))
        `((lambda (,(caar pairs))
            ,(let-make-lambdas (cdr pairs) body))
          ,(cadar pairs))))

(define-macro (let-- pairs . body)
    (let-make-lambdas pairs body))

当我使用外部函数进行代码生成时它工作正常,但下面的代码(只是一个宏)不起作用:

(define-macro (let-- pairs . body)
    (if (null? pairs)
        `((lambda () ,@body))
        `((lambda (,(caar pairs))
            ,(let-- (cdr pairs) body))
          ,(cadar pairs))))

为什么?

4

3 回答 3

3

第二种,你不想

,(let-- (cdr pairs) body)

反而

(let-- ,(cdr pairs) ,@body)

也就是说,您的直接宏实现应该是

(define-macro (let-- pairs . body)
    (if (null? pairs)
        `((lambda () ,@body))
        `((lambda (,(caar pairs))
            (let-- ,(cdr pairs) ,@body))
          ,(cadar pairs))))

您不想(let-- ...)在宏扩展时评估内部;它是应该生成的源的一部分。(当然,它很快就会被宏扩展。)为了突出这一点,考虑一个宏

(plus a b c d)

进入

(+ a (+ b (+ c d)))

它需要像这样扩展

(+ ,(car args) (plus ,@(cdr args)))

但不是

(+ ,(car args) ,(plus (cdr args)))

因为后者会尝试评估(plus '(b c d)),这是行不通的。

于 2013-10-23T19:40:23.387 回答
2

我认为约书亚为你的问题找到了答案。我只想指出Scheme标准用法syntax-rulessyntax-case. 它可能是这样的syntax-rules

;; make let* with lambdas
(define-syntax let--
  (syntax-rules ()
    ;; base case, last pair
    ((let-- ((key1 value1)) . body) 
     ((lambda (key1) . body ) value1))

    ;; default case, several
    ((let-- ((key1 value1) . kv-pairs) . body) 
     ((lambda (key1) (let-- kv-pairs . body)) value1))))

(let-- ((a 'a) (b a) (c b)) (list a b c)) ; ==> (a a a)
于 2013-10-23T19:55:14.417 回答
1

这是一个有效的 Common Lisp 版本:

(defmacro let1-- (pairs . body)
  (if (null pairs)
      `((lambda () ,@body))
      `((lambda (,(caar pairs))
         (let-- ,(cdr pairs) . ,body))
         ,(cadar pairs))))
> (macroexpand '(let1-- ((a 1) (b 2)) (+ b a)))
((LAMBDA (A) (LET-- ((B 2)) (+ B A))) 1) ;
T
> (let1-- ((a 1) (b 2)) (+ b a))
3

相应的方案版本是,我猜,

(define-macro (let-- pairs . body)
    (if (null? pairs)
        `((lambda () ,@body))
        `((lambda (,(caar pairs))
            (let-- ,(cdr pairs) . ,body))
          ,(cadar pairs))))
于 2013-10-23T19:41:41.280 回答