【问题标题】:Graham ANSI Common Lisp 6.6 Function builders: Recursive implementation of compose?Graham ANSI Common Lisp 6.6 函数构建器:组合的递归实现?
【发布时间】:2021-04-11 17:11:12
【问题描述】:

经过一番思考,我理解了 Graham 的 ANSI Common Lisp 第 6.6 章(第 110 页)中描述的 compose 函数的工作原理:

(defun compose (&rest functions)
  (destructuring-bind (fn .  fns) (nreverse functions)
    #'(lambda (&rest arg)
    (reduce #'(lambda (x y) (funcall y x))
        fns
        :initial-value (apply fn arg)))))

(setf (symbol-function 'lst-gt10p)
      (compose #'list
           #'(lambda (x) (and (> x 10) t))))

(lst-gt10p 11)

但不知何故,我无法提供 compose 的递归定义。

例如这是递归实现的尝试:

(defun rec-compose (&rest functions)
  (destructuring-bind (fn . fns) functions
    #'(lambda (&rest args)
    (cond
      ((null fns) (apply fn args))
      (t (funcall fn
              (apply #'rec-compose fns)))))))

(funcall (rec-compose #'list #'round #'sqrt) 11)

我们的想法是继续调用(funcall fn (apply #'rec-compse fns)),直到遇到基本情况(apply fn args)。然而,这返回的不是结果,而是另一个闭包..

有什么想法吗?

【问题讨论】:

    标签: common-lisp


    【解决方案1】:

    正如帖子中所定义的,每次调用 rec-compose 时都会创建一个函数。由于rec-compose被递归调用,它试图创建一个返回函数的函数,该函数返回一个函数......

    一种解决方案是在rec-compose 返回的匿名函数内部创建一个辅助函数,该函数本身被递归调用,这样递归就不会不断堆积函数:

    (defun rec-compose (&rest functions)
      #'(lambda (&rest args)
          (labels ((combine (functions)
                     (destructuring-bind (fn . fns) functions
                       (if (null fns)
                           (apply fn args)
                           (funcall fn (funcall #'combine fns))))))
            (combine functions))))
    
    CL-USER> (funcall (rec-compose #'sqrt #'+) 9 16)
    5.0
    

    【讨论】:

    • 感谢您的帮助,现在看起来很明显了。显然,我仍然在处理所有这些递归的东西时遇到了严重的问题..
    猜你喜欢
    • 2020-06-26
    • 1970-01-01
    • 2020-02-19
    • 1970-01-01
    • 2018-05-16
    • 2020-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多