【问题标题】:(compose) in Common Lisp(撰写)在 Common Lisp 中
【发布时间】:2013-10-17 11:04:46
【问题描述】:

我们在 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)))))

compose 的参数列表被反转和解包,它的(现在是第一个)元素绑定到“fn1”,其余元素绑定到“rest”。 最外层 lambda 的主体是 reduce: (funcall fi (funcall fi-1 ... ) ),操作数倒序恢复初始操作数。

1) 最外层的 lambda 表达式的作用是什么?即,它从哪里得到它的“参数”?它是指定为解构绑定的第一个参数的数据结构吗? 2) 最里面的 lambda 从哪里获取它的两个参数?

我的意思是我可以理解代码的作用,但词法范围对我来说还是有点神秘。 期待任何和所有的cmets! 提前致谢, //马可

【问题讨论】:

  • 为什么都是吊括号?
  • 抱歉,我在stackoverflow.com/questions/5928106/…没有看到关于这个的讨论
  • @Marcin ,引导眼睛;)这是不好的做法吗?我还是个菜鸟
  • 它可能是第一个具有 sexpr 语法的苹果 dylan 版本
  • Marco Zocca,@Marcin 的观点,更简洁地说,大多数 Lisp 用户阅读的是缩进,而不是括号。

标签: functional-programming lisp common-lisp


【解决方案1】:

如果您先考虑几个实际示例,可能会更容易:

(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)))))

【讨论】:

  • 感谢您的示例和解释,这绝对澄清了问题!
【解决方案2】:

1) 最外层的 lambda 会为您创建一个闭包,因为 (combine ...) 的结果是一个计算其他函数组合的函数。

2) 最里面的 lambda 从函数 reduce 中获取ists 参数。 Reduce 采用两个参数的函数(最里面的 lambda)并将其逐步应用于列表,例如

 (reduce #'- '(1 2 3 4))  is   (- (- (- 1 2) 3) 4)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-18
    • 2015-12-22
    • 2019-11-16
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多