我正在学习Scheme中的宏系统是如何工作的,我正在尝试使我的代码看起来更像JavaScript-y。所以我想我会从function
宏开始。这就是我想要一个函数定义的样子:
(function id (x) x)
它应扩展到以下内容:
(define (id x) x)
所以我写一个宏如下:
(define-syntax function
(lambda (name args . body)
`(define (,name ,@args) ,@body)))
但是当我使用它时,我收到以下错误(在Chicken Scheme中):
Error: during expansion of (define ...) - in `define' - lambda-list expected: (define ((function id (x) x) . #<procedure (rename sym1348)>) #<procedure (compare s11400 s21401)>)
Call history:
<syntax> (function id (x) x)
<eval> (##sys#cons (##core#quote define) (##sys#cons (##sys#cons name args) body))
<eval> (##sys#cons (##sys#cons name args) body)
<eval> (##sys#cons name args) <--
我哪里错了?另外,如何阅读此类错误消息以便自己调试程序?
答案 0 :(得分:4)
在Scheme中,使用syntax-rules():
(define-syntax function
(syntax-rules ()
((function name (args ...) body ...)
(define (name args ...) body ...))))
您看到的错误显然是Chicken Scheme的编译器期望第二种形式的define-syntax
是宏扩展过程 - 它们通常需要用于重命名和比较标识符的参数。宏中的lambda
不会生成合适的函数 - syntax-rules
会这样做。
以上保证卫生。
答案 1 :(得分:2)
根据Chicken文档,您定义宏的方式不正确。您的代码似乎更受Common Lisp宏的启发。查看带有变压器功能的define-syntax
的文档here:
宏应定义为:
(define-syntax function
(lambda (expr inject compare)
`(define (,(cadr expr) ,@(caddr expr)) ,(cadddr expr))))
expr是整个宏表达式,即(function id (x) x)
,而inject和compare是在宏扩展时传递给宏的特殊效用函数。