我的宏在 Common Lisp 中的部分应用有问题
A problem with my macro for partial application in Common Lisp
我正在尝试制作一个宏来实现 Common Lisp 中的部分应用。这是我对如何在伪代码中实现它的想法:
If my argument list is null, return the function body
Otherwise, cons together "lambda" with the first argument with a recursive call to "partial-lambda" again
(lambda (x y z) (+ x y z) => (lambda (x) (lambda (y) (lambda (z) (+ x y z))))
这是我的代码:
(defmacro partial-lambda (params &rest body)
(if (null params) body
(lambda ((car params)) (partial-lambda (cdr params) body))))
(partial-lambda (x y z) (+ x y z))
不幸的是,SBCL 给我这个错误:
; in: DEFMACRO PARTIAL-LAMBDA
; (LAMBDA (CAR PARAMS) (PARTIAL-LAMBDA (CDR PARAMS) BODY))
; ==>
; #'(LAMBDA (CAR PARAMS) (PARTIAL-LAMBDA (CDR PARAMS) BODY))
;
; caught STYLE-WARNING:
; The variable CAR is defined but never used.
; file: /Users/caspianahlberg/Desktop/Programming/Lisp/partial_application.lisp
; in: DEFMACRO PARTIAL-LAMBDA
; (PARTIAL-LAMBDA (CDR PARAMS) BODY)
;
; caught STYLE-WARNING:
; undefined function: COMMON-LISP-USER::PARTIAL-LAMBDA
;
; compilation unit finished
; Undefined function:
; PARTIAL-LAMBDA
; caught 2 STYLE-WARNING conditions
STYLE-WARNING:
PARTIAL-LAMBDA is being redefined as a macro when it was previously assumed to be a function.
为什么它抱怨 car
从未被使用?我觉得这真的很令人困惑。熟悉 CL 宏的人知道我做错了什么吗?
试试这个:
(defmacro partial-lambda (params &rest body)
(if (null params) `(progn ,@body)
`(lambda (,(car params)) (partial-lambda ,(cdr params) ,@body))))
CL-USER 43 > (partial-lambda (x y z) (+ x y z))
#<anonymous interpreted function 40300008DC>
CL-USER 44 > (funcall * 10)
#<anonymous interpreted function 403000094C>
CL-USER 45 > (funcall * 15)
#<anonymous interpreted function 40300009BC>
CL-USER 46 > (funcall * 3)
28
Backquote is variant of QUOTE,允许在其中取消引用。 , 当你想取消引用部分内的内容时使用(该表达式被值替换)。并且 ,@(取消引用拼接)取消引用某些内容,替换它并删除该值周围的括号。这些操作在 Lisp 宏中很常用。
编辑: (car body)
替换为 `(progn ,@body)
以处理正文中包含更多表达式的输入:(partial-lambda (x y z) (print 5)(+ x y z))
.
语法错误
(lambda ((car params)) (partial-lambda (cdr params) body))
Common Lisp 需要一个参数列表作为 lambda 形式的第二个元素。参数是一个符号。不评估参数列表。
您的代码有一个列表 (car params)
作为第一个参数。但是 Common Lisp 需要一个符号。
您的示例也不符合您显示的错误。
可能你做到了:
(defmacro partial-lambda (params &rest body)
(if (null params)
body
(lambda (car params) (partial-lambda (cdr params) body))))
但是你用参数car
和params
定义了一个参数列表。这是没有意义的。这就是 Lisp 编译器抱怨变量 car
未被使用的原因。
宏操作代码
请记住,您的宏需要 return 代码。使用列表运算符或反引号表达式创建代码。
反引号表达式看起来像这样(参见 Martin Půda 的回答):
`(lambda (,(car params)) (partial-lambda ,(cdr params) ,@body))
反引号允许评估列表模板的选定部分。 逗号 计算并插入结果。 逗号对结果列表求值拼接在.
我正在尝试制作一个宏来实现 Common Lisp 中的部分应用。这是我对如何在伪代码中实现它的想法:
If my argument list is null, return the function body
Otherwise, cons together "lambda" with the first argument with a recursive call to "partial-lambda" again
(lambda (x y z) (+ x y z) => (lambda (x) (lambda (y) (lambda (z) (+ x y z))))
这是我的代码:
(defmacro partial-lambda (params &rest body)
(if (null params) body
(lambda ((car params)) (partial-lambda (cdr params) body))))
(partial-lambda (x y z) (+ x y z))
不幸的是,SBCL 给我这个错误:
; in: DEFMACRO PARTIAL-LAMBDA
; (LAMBDA (CAR PARAMS) (PARTIAL-LAMBDA (CDR PARAMS) BODY))
; ==>
; #'(LAMBDA (CAR PARAMS) (PARTIAL-LAMBDA (CDR PARAMS) BODY))
;
; caught STYLE-WARNING:
; The variable CAR is defined but never used.
; file: /Users/caspianahlberg/Desktop/Programming/Lisp/partial_application.lisp
; in: DEFMACRO PARTIAL-LAMBDA
; (PARTIAL-LAMBDA (CDR PARAMS) BODY)
;
; caught STYLE-WARNING:
; undefined function: COMMON-LISP-USER::PARTIAL-LAMBDA
;
; compilation unit finished
; Undefined function:
; PARTIAL-LAMBDA
; caught 2 STYLE-WARNING conditions
STYLE-WARNING:
PARTIAL-LAMBDA is being redefined as a macro when it was previously assumed to be a function.
为什么它抱怨 car
从未被使用?我觉得这真的很令人困惑。熟悉 CL 宏的人知道我做错了什么吗?
试试这个:
(defmacro partial-lambda (params &rest body)
(if (null params) `(progn ,@body)
`(lambda (,(car params)) (partial-lambda ,(cdr params) ,@body))))
CL-USER 43 > (partial-lambda (x y z) (+ x y z))
#<anonymous interpreted function 40300008DC>
CL-USER 44 > (funcall * 10)
#<anonymous interpreted function 403000094C>
CL-USER 45 > (funcall * 15)
#<anonymous interpreted function 40300009BC>
CL-USER 46 > (funcall * 3)
28
Backquote is variant of QUOTE,允许在其中取消引用。 , 当你想取消引用部分内的内容时使用(该表达式被值替换)。并且 ,@(取消引用拼接)取消引用某些内容,替换它并删除该值周围的括号。这些操作在 Lisp 宏中很常用。
编辑: (car body)
替换为 `(progn ,@body)
以处理正文中包含更多表达式的输入:(partial-lambda (x y z) (print 5)(+ x y z))
.
语法错误
(lambda ((car params)) (partial-lambda (cdr params) body))
Common Lisp 需要一个参数列表作为 lambda 形式的第二个元素。参数是一个符号。不评估参数列表。
您的代码有一个列表 (car params)
作为第一个参数。但是 Common Lisp 需要一个符号。
您的示例也不符合您显示的错误。
可能你做到了:
(defmacro partial-lambda (params &rest body)
(if (null params)
body
(lambda (car params) (partial-lambda (cdr params) body))))
但是你用参数car
和params
定义了一个参数列表。这是没有意义的。这就是 Lisp 编译器抱怨变量 car
未被使用的原因。
宏操作代码
请记住,您的宏需要 return 代码。使用列表运算符或反引号表达式创建代码。
反引号表达式看起来像这样(参见 Martin Půda 的回答):
`(lambda (,(car params)) (partial-lambda ,(cdr params) ,@body))
反引号允许评估列表模板的选定部分。 逗号 计算并插入结果。 逗号对结果列表求值拼接在.