(撰写)在Common Lisp中

ocr*_*amz 8 lisp functional-programming 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) (funcall f v)) 
                rest
                :initial-value (apply fn1 args)))))
Run Code Online (Sandbox Code Playgroud)

要构成的参数列表是反向和解包的,其(现在是第一个)元素绑定到'fn1',其余元素绑定到'rest'.最外层lambda的主体是reduce :( funcall fi(funcall fi-1 ...)),操作数按反转顺序恢复初始值.

1)最外层lambda表达式的作用是什么?也就是说,它从哪里获得'args'?它是指定为destructuring-bind的第一个参数的数据结构吗?2)最里面的lambda从哪里取两个参数?

我的意思是我可以欣赏代码的作用但是词法范围对我来说仍然有点神秘.期待任何和所有评论!在此先感谢,Marco

650*_*502 11

如果你先考虑几个实际例子,这可能会更容易:

(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)))))
Run Code Online (Sandbox Code Playgroud)

所以最外层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)))))
Run Code Online (Sandbox Code Playgroud)