Functional programming (撰写)在公共Lisp中

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

我们在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) (funcall f v)) 
                rest
                :initial-value (apply fn1 args)))))
要组合的参数列表被反转并解压,其(现在是第一个)元素绑定到“fn1”,其余元素绑定到“rest”。 最外层lambda的主体是reduce:(funcall-fi(funcall-fi-1…),操作数按相反顺序还原初始操作数

1) 最外层lambda表达式的作用是什么?也就是说,它的“args”来自哪里?是否将数据结构指定为解构绑定的第一个参数? 2) 最里面的lambda从哪里获取它的两个参数

我的意思是,我可以理解代码的功能,但词法范围对我来说还是有点神秘。 期待所有评论! 提前感谢,, //Marco

1)最外层的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用户阅读缩进,而不是括号。谢谢你的示例和解释,这肯定能澄清问题!