我正在学习 Scheme 中的宏系统,我认为实现 curried 函数将是一个好的开始。这是我做的:
(define-syntax function
(syntax-rules ()
((_ () body ...) (lambda () body ...))
((_ (param) body ...) (lambda (param) body ...))
((_ (param_1 param_2 params ...) body ...) (lambda (param_1 . rest)
(let ((k (function (param_2 params ...) body ...)))
(if (null? rest) k (apply k rest)))))
((_ name params body ...) (define name (function params body ...)))))
此代码按预期工作。例如我可以定义一个add
函数如下:
(function add (x y) (+ x y))
然后我可以正常调用它:
(add 2 3) ; => 5
此外,我可以轻松地部分应用它:
(map (add 10) '(2 3 5 7)) ; => (12 13 15 17)
现在我正在考虑允许对带有剩余参数的函数进行柯里化。所以我添加了一个新的语法规则:
((_ (param . params) body ...) (lambda (param . params) body ...))
不幸的是,当我尝试使用此规则创建函数时,它给了我一个错误:
(function add (x . y) (apply + `(,x ,@y)))
这是错误消息:
Error: invalid syntax in macro form: (x . y)
Call history:
<eval> (##sys#= len7 0)
<eval> (loop11 (##sys#cdr l6) (##sys#+ len7 -1))
<eval> (##sys#cdr l6)
<eval> (##sys#+ len7 -1)
<eval> (##sys#= len7 0)
<eval> (loop11 (##sys#cdr l6) (##sys#+ len7 -1))
<eval> (##sys#cdr l6)
<eval> (##sys#+ len7 -1)
<eval> (##sys#= len7 0)
<eval> (##sys#eq? l6 (quote ()))
<eval> (##sys#car tail15)
<eval> (##sys#cdr tail15)
<eval> (##sys#cons (rename14 (##core#syntax lambda)) (##sys#cons param body))
<eval> (rename14 (##core#syntax lambda))
<eval> (##sys#cons param body)
<syntax> (##core#lambda add (x . y) (apply + (quasiquote ((unquote x) (unquote-splicing y))))) <-
我究竟做错了什么?