比如现在有一个下面这样的函数列表(注意: 这里只是为了举例方便,实际可能远远不止这几个函数。)
'(fun1 fun2 fun3)
函数列表是作为参数来传递的,请问用什么样的 form 才能达到如下的效果:
(fun1 (fun2 (fun3 arg)))
**PS:**顺序不重要
比如现在有一个下面这样的函数列表(注意: 这里只是为了举例方便,实际可能远远不止这几个函数。)
'(fun1 fun2 fun3)
函数列表是作为参数来传递的,请问用什么样的 form 才能达到如下的效果:
(fun1 (fun2 (fun3 arg)))
**PS:**顺序不重要
(defun demo( args &rest funlist )
(dolist (f (reverse funlist))
(setq args (funcall f args))
)
)
(demo "hello" 'message 'print)
谢谢!
补充一点:顺序不重要的情形下,可以不用加 reverse
函数。
来个递归版的:
(defun recall (arg fn &rest rest-fns)
(if (null rest-fns)
(funcall fn arg)
(funcall fn (apply 'recall arg (car rest-fns) (cdr rest-fns)))))
(defun add1(num)
(+ num 1))
(recall 0 'add1 'add1 'add1)
;; => 3
这个本质就是 foldRight。dash.el
里面就有 -reduce-r-from
:
(-reduce-r-from #'funcall 2 '(1+ 1+))
或者用 Emacs 25 以后自带的 seq.el
,这个只有 foldLeft,需要 reverse 列表才能和 foldRight 一样。不过既然楼主不关心顺序,下面就没加 nreverse
:
(seq-reduce (lambda (acc x) (funcall x acc)) '(1+ 1+) 2)
cl-reduce
也是可以的(和 seq-reduce
类似):
(cl-reduce (lambda (acc x) (funcall x acc)) '(1+ 1+) :initial-value 2)
前面没认真看,以为参数必须是不定参 &rest
,把问题搞复杂了(更😅的是我第一反应竟然是定义一个 add1
, 而不是用 1+
)。固定参不需要 apply
:
(defun recall (arg fn-list)
(if fn-list
(funcall (car fn-list) (recall arg (cdr fn-list)))
arg))
(recall 0 '(1+ 1+ 1+))
;; => 3