创建一个可以将 lambda 应用于上下文中的列表的 Lisp 宏
Creating a Lisp macro that can apply a lambda to a list within a context
基本上我正在尝试编写一个 Common Lisp 宏定义为:
(defmacro applyfunct (function arguments variables))
将作为参数 function
给出的函数应用到参数 arguments
(这是一个将函数应用到的参数列表),在必要时使用给定的变量在列表列表 variables
中添加它。所以 return 使用这些参数调用时的值是这样的:
(applyfunct + (7 5) ((x 1) (y 2)))
将是 12,考虑到 7+5=12,并且不需要上下文变量 x 和 y 来将函数应用于参数。但是,当它确实需要给定的上下文变量时:
(applyfunct (lambda (x y) (+ (* a x) (* y b)) (4 2) ((a 2) (b 4))))
如果函数中需要这些变量来计算 return 16,它应该使用这些变量,因为:
(applyfunct (lambda (x y) (+ (* a x) (* y b)) (4 2) ((a 8) (b 1))))
; 4 2 8 4 2 1
; (+ (* 8 4) (* 2 1)) => 34
希望我在这里的评论能清楚地说明我想做什么。我目前拥有的是:
(defmacro applyfunct (function arguments variables)
(let ( ((car (first contents)) (cdar (first contents))
((car (second contents)) (cdar (second contents))
但我不知道如何继续...
(apply function arguments)
仅适用于函数为 + 的第一个示例调用,不适用于使用 lambda 的第二个函数调用。我在这里错过了什么吗?我应该以某种方式使用 ` 或 #' 吗?注意:我正在尝试尽可能地在功能上进行编程(最小到没有副作用,例如,不使用 setq)。我也在使用 Common Lisp 的 CLISP 实现。
据我所知,apply
仅适用于第二个示例 (lambda
),不适用于 +
。
但请记住,您是在编写宏,它可以根据需要构造程序代码(例如(+ 7 5)
或((lambda (x y) ...) 4 2)
)。
第一步是使函数调用起作用(暂时忽略 variables
)。在 Lisp 中,函数调用的句法形式是一个列表,其第一个元素(头)是函数,其余元素(尾)是函数参数。这个结构可以被构建,例如通过使用 cons
:
(defmacro applyfunct (function arguments variables)
(cons function arguments))
或者,使用`
的语法糖:
(defmacro applyfunct (function arguments variables)
`(,function ,@arguments))
(`
就像一个代码模板,,
标记要插入变量的位置,,@
额外地展平列表。)
现在,要使 variables
起作用,let
可用于提供绑定(如在您的代码中)。但是,不需要手动解构variables
;它已经具有 let
绑定列表的正确形状:
(defmacro applyfunct (function arguments variables)
`(let ,variables
(,function ,@arguments)))
我们可以测试这个宏:
(print (macroexpand-1 '(applyfunct (lambda (x y) (+ (* a x) (* y b))) (4 2) ((a 8) (b 1)))))
; by the way, one of the ') is misplaced in your example: ----------^
生成此输出:
(LET ((A 8) (B 1)) ((LAMBDA (X Y) (+ (* A X) (* Y B))) 4 2))
...这正是我们想要的。
基本上我正在尝试编写一个 Common Lisp 宏定义为:
(defmacro applyfunct (function arguments variables))
将作为参数 function
给出的函数应用到参数 arguments
(这是一个将函数应用到的参数列表),在必要时使用给定的变量在列表列表 variables
中添加它。所以 return 使用这些参数调用时的值是这样的:
(applyfunct + (7 5) ((x 1) (y 2)))
将是 12,考虑到 7+5=12,并且不需要上下文变量 x 和 y 来将函数应用于参数。但是,当它确实需要给定的上下文变量时:
(applyfunct (lambda (x y) (+ (* a x) (* y b)) (4 2) ((a 2) (b 4))))
如果函数中需要这些变量来计算 return 16,它应该使用这些变量,因为:
(applyfunct (lambda (x y) (+ (* a x) (* y b)) (4 2) ((a 8) (b 1))))
; 4 2 8 4 2 1
; (+ (* 8 4) (* 2 1)) => 34
希望我在这里的评论能清楚地说明我想做什么。我目前拥有的是:
(defmacro applyfunct (function arguments variables)
(let ( ((car (first contents)) (cdar (first contents))
((car (second contents)) (cdar (second contents))
但我不知道如何继续...
(apply function arguments)
仅适用于函数为 + 的第一个示例调用,不适用于使用 lambda 的第二个函数调用。我在这里错过了什么吗?我应该以某种方式使用 ` 或 #' 吗?注意:我正在尝试尽可能地在功能上进行编程(最小到没有副作用,例如,不使用 setq)。我也在使用 Common Lisp 的 CLISP 实现。
据我所知,apply
仅适用于第二个示例 (lambda
),不适用于 +
。
但请记住,您是在编写宏,它可以根据需要构造程序代码(例如(+ 7 5)
或((lambda (x y) ...) 4 2)
)。
第一步是使函数调用起作用(暂时忽略 variables
)。在 Lisp 中,函数调用的句法形式是一个列表,其第一个元素(头)是函数,其余元素(尾)是函数参数。这个结构可以被构建,例如通过使用 cons
:
(defmacro applyfunct (function arguments variables)
(cons function arguments))
或者,使用`
的语法糖:
(defmacro applyfunct (function arguments variables)
`(,function ,@arguments))
(`
就像一个代码模板,,
标记要插入变量的位置,,@
额外地展平列表。)
现在,要使 variables
起作用,let
可用于提供绑定(如在您的代码中)。但是,不需要手动解构variables
;它已经具有 let
绑定列表的正确形状:
(defmacro applyfunct (function arguments variables)
`(let ,variables
(,function ,@arguments)))
我们可以测试这个宏:
(print (macroexpand-1 '(applyfunct (lambda (x y) (+ (* a x) (* y b))) (4 2) ((a 8) (b 1)))))
; by the way, one of the ') is misplaced in your example: ----------^
生成此输出:
(LET ((A 8) (B 1)) ((LAMBDA (X Y) (+ (* A X) (* Y B))) 4 2))
...这正是我们想要的。