Functional programming (撰写)在公共Lisp中
我们在p.Graham的“ANSI Common Lisp”(第110页)中找到了这个函数生成器来实现组合。 参数是n>0个带引号的函数名。我不完全理解它,所以我将在这里引用代码,并在下面指定我的问题:Functional programming (撰写)在公共Lisp中,functional-programming,lisp,common-lisp,Functional Programming,Lisp,Common Lisp,我们在p.Graham的“ANSI Common Lisp”(第110页)中找到了这个函数生成器来实现组合。 参数是n>0个带引号的函数名。我不完全理解它,所以我将在这里引用代码,并在下面指定我的问题: (defun compose (&rest fns) (destructuring-bind (fn1 . rest) (reverse fns) #'(lambda (&rest args) (reduce #'(lambda (v f) (func
(defun compose (&rest fns)
(destructuring-bind (fn1 . rest) (reverse fns)
#'(lambda (&rest args)
(reduce #'(lambda (v f) (funcall f v))
rest
:initial-value (apply fn1 args)))))
要组合的参数列表被反转并解压,其(现在是第一个)元素绑定到“fn1”,其余元素绑定到“rest”。
最外层lambda的主体是reduce:(funcall-fi(funcall-fi-1…),操作数按相反顺序还原初始操作数
1) 最外层lambda表达式的作用是什么?也就是说,它的“args”来自哪里?是否将数据结构指定为解构绑定的第一个参数?
2) 最里面的lambda从哪里获取它的两个参数
我的意思是,我可以理解代码的功能,但词法范围对我来说还是有点神秘。
期待所有评论!
提前感谢,,
//Marco1)最外层的lambda为您创建一个闭包,因为(combine…)的结果是一个计算其他函数组成的函数
2) 最内层的lambda从函数reduce获取ists参数。Reduce接受一个包含两个参数的函数(最内层的lambda),并将其逐步应用于列表,例如
(reduce #'- '(1 2 3 4)) is (- (- (- 1 2) 3) 4)
如果你先考虑几个实际的例子,可能会更容易:
(defun compose1 (a)
(lambda (&rest args)
(apply a args)))
(defun compose2 (a b)
(lambda (&rest args)
(funcall a (apply b args))))
(defun compose3 (a b c)
(lambda (&rest args)
(funcall a (funcall b (apply c args)))))
因此,最外面的lambda
是返回值:一个接受任何参数的函数,它所做的是应用最后一个函数,并按照从最后一个函数得到的结果的相反顺序链接所有其他函数
注:compose1
可以更简单地定义为(defun compose1(a)a)
可能需要一个相当但效率较低的版本
(defun compose (&rest functions)
(if (= (length functions) 1)
(car functions)
(lambda (&rest args)
(funcall (first functions)
(apply (apply #'compose (rest functions))
args)))))
为什么会有这么多悬而未决的问题?很抱歉,我没有看到@Marcin上关于这个问题的讨论,来引导大家的注意力;)这是坏习惯吗?我还是有点怀疑苹果dylan的第一个版本是否有sexpr syntaxMarco Zocca,@Marcin的观点,更简洁地说,是大多数Lisp用户阅读缩进,而不是括号。谢谢你的示例和解释,这肯定能澄清问题!