common-lisp - Graham ANSI Common Lisp 6.6 函数构建器:组合的递归实现?
问题描述
经过一番思考,我理解了 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
推荐阅读
- html - Powershell 将字符串数组传递给 ConvertTo-Html
- css - 我无法覆盖 justify-content
- c++ - 解释为什么它没有返回它应该返回的内容
- java - 春季批处理文件编写器直接写入亚马逊 s3 存储,无需 PutObjectRequest
- matlab - 如何为一组输入创建表达式?
- javascript - 对象不保持顺序,但可以正确增加属性。为什么?
- php - 如何上传具有两个不同文件夹的两个文件?
- mongodb - 在已启动实例上使用 EC2 用户数据的 MongoDB 启动脚本
- python-3.x - 如何使用单字节异或密码打破重复密钥异或挑战
- java - LinkedList中Iterator的方法remove()