创建一个可以将lambda应用于上下文中的列表的Lisp宏

时间:2018-02-12 06:14:00

标签: lambda macros lisp common-lisp clisp

基本上我正在尝试编写一个定义为:

的Common Lisp宏
(defmacro applyfunct (function arguments variables))

将作为参数function给出的函数应用于参数arguments(这是应用函数的参数列表),必要时使用给定的变量在列表variables中。所以用这些参数调用它时的返回值如下:

(applyfunct + (7 5) ((x 1) (y 2)))
考虑到7 + 5 = 12,

将是12,并且不需要上下文变量x和y来将函数应用于参数。但是当它确实需要给出上下文变量时:

(applyfunct (lambda (x y) (+ (* a x) (* y b)) (4 2) ((a 2) (b 4))))

如果在给予评估返回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实现。

1 个答案:

答案 0 :(得分:4)

据我所知,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))

......这正是我们想要的。