如何解决Graham ANSI Common Lisp 6.6 函数构建器:compose 的递归实现?
经过深思熟虑后,我理解了 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)
。然而这返回的不是结果而是另一个闭包..
有什么想法吗?
解决方法
如帖子中所定义,每次调用 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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。