Macros 为什么这个lisp递归宏不';不行?
我在guile中使用了宏let--(比如let*使用lambdas):Macros 为什么这个lisp递归宏不';不行?,macros,lambda,lisp,scheme,guile,Macros,Lambda,Lisp,Scheme,Guile,我在guile中使用了宏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-mac
(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))))
为什么?第二,你不想
,(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))))
您不希望在宏展开时计算内部(让--…)
;它是应该生成的源代码的一部分。(当然,它很快就会被宏文件化)。
(plus a b c d)
进入
它需要像这样扩张
(+ ,(car args) (plus ,@(cdr args)))
但不是
(+ ,(car args) ,(plus (cdr args)))
因为后者将尝试计算
(plus'(bcd))
,这将不起作用。在第二种情况下,您不希望
,(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))))
您不希望在宏展开时计算内部(让--…)
;它是应该生成的源代码的一部分。(当然,它很快就会被宏文件化)。
(plus a b c d)
进入
它需要像这样扩张
(+ ,(car args) (plus ,@(cdr args)))
但不是
(+ ,(car args) ,(plus (cdr args)))
因为后者将尝试计算
(plus'(b c d))
,这将不起作用。这里是一个通用的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))))
以下是一个通用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))))
我想约书亚找到了你问题的答案。我只想指出,
Scheme
标准使用语法规则
和语法大小写
。在语法规则中可能是这样的:
;; 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)
我想约书亚找到了你问题的答案。我只想指出,Scheme
标准使用语法规则
和语法大小写
。在语法规则中可能是这样的:
;; 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)
忘记带括号了吗p宏调用似乎与其定义不一致:点丢失。@sds
用于定义Common Lisp中的&rest
列表。在第一种情况下,jcubic定义了一个函数来执行代码扩展,而宏确实包含了
@JoshuaTaylor:我的意思是,宏的调用必须有一个
(如我的回答中所示)或一个@
(如你的回答中所示)@sds哦,我明白你的意思了。定义中的(let--…)
可能是(let--(cdr pairs).body)
。对(只要其他问题得到解决)。对不起,我误解了。忘了带括号了吗p宏调用似乎与其定义不一致:点丢失。@sds
用于定义Common Lisp中的&rest
列表。在第一种情况下,jcubic定义了一个函数来执行代码扩展,而宏确实包含了
@JoshuaTaylor:我的意思是,宏的调用必须有一个
(如我的回答中所示)或一个@
(如你的回答中所示)@sds哦,我明白你的意思了。定义中的(let--…)
可能是(let--(cdr pairs).body)
。对(只要其他问题得到解决)。对不起,我误解了。我更喜欢支持它们的lisp宏和scheme实现,但还是要感谢你的回答。我更喜欢支持它们的lisp宏和scheme实现,但还是要感谢你的回答。