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

创建可以将lambda应用于上下文中列表的Lisp宏,lambda,macros,lisp,common-lisp,clisp,Lambda,Macros,Lisp,Common Lisp,Clisp,基本上,我正在尝试编写一个通用Lisp宏,定义为: (defmacro applyfunct (function arguments variables)) 它将作为参数函数给定的函数应用于参数参数(这是应用函数的参数列表),必要时,使用列表变量中给定的变量。因此,使用以下参数调用时的返回值: (applyfunct + (7 5) ((x 1) (y 2))) 将是12,考虑到7+5=12,并且上下文变量x和y不需要将函数应用于参数。但是,当它确实需要给定的上下文变量时: (applyfu

基本上,我正在尝试编写一个通用Lisp宏,定义为:

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

(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))))
如果函数中需要这些变量来计算返回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
),而不是
+

但请记住,您正在编写一个宏,它可以根据需要构造程序代码(如
(+75)
((lambda(xy)…)42)

第一步是使函数调用工作(暂时忽略变量)。在Lisp中,函数调用的语法形式是一个列表,其第一个元素(head)是函数,其余元素(tail)是函数参数。该结构可通过使用
cons
等方式构建:

(defmacro applyfunct (function arguments variables)
    (cons function arguments))
或者,使用
`
的语法糖:

(defmacro applyfunct (function arguments variables)
    `(,function ,@arguments))
`
的作用类似于一个代码模板,其中
标记要插入变量的位置,
,@
还可以将列表展平。)

现在,为了使
变量
起作用,
let
可以用来提供绑定(就像在代码中一样)。但是,不需要手动分解
变量
;对于
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))

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

这看起来像一个练习?一般来说,这样的宏看起来不是很有用。它可以通过一个非常简单的源代码翻译来实现(参见melpomene的答案),这非常奇怪,几乎没有关于应用程序的内容。我想您可能会在实现中混合使用
apply
,并将
apply
作为典型的
eval
解释器。在后者中,有一个代表环境的参数是正常的。”