Common lisp 如何将函数列表应用于单个变量?
我想写一个函数/宏Common lisp 如何将函数列表应用于单个变量?,common-lisp,Common Lisp,我想写一个函数/宏 (defun apply-funcs (functions value) ...) 因此,调用apply funcs list'f'g'hx将执行与hgfx等效的操作。如何实现这一点?看起来您希望将函数列表缩减为一个值 CL-USER> (defun apply-funcs (functions value) (reduce (lambda (memo fn) (funcall fn memo)) funct
(defun apply-funcs (functions value) ...)
因此,调用apply funcs list'f'g'hx将执行与hgfx等效的操作。如何实现这一点?看起来您希望将函数列表缩减为一个值
CL-USER> (defun apply-funcs (functions value)
(reduce (lambda (memo fn) (funcall fn memo))
functions :initial-value value))
CL-USER> (apply-funcs
(list (lambda (n) (+ 3 n))
(lambda (n) (- n 2))
(lambda (n) (* 2 n)))
6)
14
CL-USER>
你可能知道reduce是其他语言中的fold。我使用funcall而不是apply,因为您已经说过要在上面使用funcs列表'f'g'hx=>hgfx。如果x是一个值列表,则使用apply,每个元素都要绑定到一个单独的参数。例如,如果你想做像
(apply-funcs
(list (lambda (a b c)
(list (+ a c) (+ b c)))
(lambda (d e)
(+ d e)))
(list 1 2 3))
然后在apply funcs的定义中需要apply而不是funcall
根据情况,您也可以选择宏路径
(defmacro ->> (value &body functions)
(reduce
(lambda (memo fn) `(funcall ,fn ,memo))
functions :initial-value value))
这基本上是一样的
CL-USER> (->> 6
(lambda (n) (+ 3 n))
(lambda (n) (- n 2))
(lambda (n) (* 2 n)))
14
CL-USER> (macroexpand
'(->> 6
(lambda (n) (+ 3 n))
(lambda (n) (- n 2))
(lambda (n) (* 2 n))))
(FUNCALL (LAMBDA (N) (* 2 N))
(FUNCALL (LAMBDA (N) (- N 2))
(FUNCALL (LAMBDA (N) (+ 3 N)) 6)))
T
看起来您希望将函数列表缩减为一个值
CL-USER> (defun apply-funcs (functions value)
(reduce (lambda (memo fn) (funcall fn memo))
functions :initial-value value))
CL-USER> (apply-funcs
(list (lambda (n) (+ 3 n))
(lambda (n) (- n 2))
(lambda (n) (* 2 n)))
6)
14
CL-USER>
你可能知道reduce是其他语言中的fold。我使用funcall而不是apply,因为您已经说过要在上面使用funcs列表'f'g'hx=>hgfx。如果x是一个值列表,则使用apply,每个元素都要绑定到一个单独的参数。例如,如果你想做像
(apply-funcs
(list (lambda (a b c)
(list (+ a c) (+ b c)))
(lambda (d e)
(+ d e)))
(list 1 2 3))
然后在apply funcs的定义中需要apply而不是funcall
根据情况,您也可以选择宏路径
(defmacro ->> (value &body functions)
(reduce
(lambda (memo fn) `(funcall ,fn ,memo))
functions :initial-value value))
这基本上是一样的
CL-USER> (->> 6
(lambda (n) (+ 3 n))
(lambda (n) (- n 2))
(lambda (n) (* 2 n)))
14
CL-USER> (macroexpand
'(->> 6
(lambda (n) (+ 3 n))
(lambda (n) (- n 2))
(lambda (n) (* 2 n))))
(FUNCALL (LAMBDA (N) (* 2 N))
(FUNCALL (LAMBDA (N) (- N 2))
(FUNCALL (LAMBDA (N) (+ 3 N)) 6)))
T
来自Alexandria库的compose和multiple value compose函数,包括用于compose的编译器宏。你所描述的似乎与
(funcall (alexandria:compose #'h #'g #'f) x)
以致
(defun apply-funcs (functions value)
(funcall (apply #'compose (reverse functions)) value))
会做你想做的-尽管我怀疑直接调用compose可能更有效,这取决于上下文
图书馆的职能包括:
(defun compose (function &rest more-functions)
"Returns a function composed of FUNCTION and MORE-FUNCTIONS that applies its
arguments to to each in turn, starting from the rightmost of MORE-FUNCTIONS,
and then calling the next one with the primary value of the last."
(declare (optimize (speed 3) (safety 1) (debug 1)))
(reduce (lambda (f g)
(let ((f (ensure-function f))
(g (ensure-function g)))
(lambda (&rest arguments)
(declare (dynamic-extent arguments))
(funcall f (apply g arguments)))))
more-functions
:initial-value function))
(define-compiler-macro compose (function &rest more-functions)
(labels ((compose-1 (funs)
(if (cdr funs)
`(funcall ,(car funs) ,(compose-1 (cdr funs)))
`(apply ,(car funs) arguments))))
(let* ((args (cons function more-functions))
(funs (make-gensym-list (length args) "COMPOSE")))
`(let ,(loop for f in funs for arg in args
collect `(,f (ensure-function ,arg)))
(declare (optimize (speed 3) (safety 1) (debug 1)))
(lambda (&rest arguments)
(declare (dynamic-extent arguments))
,(compose-1 funs))))))
来自Alexandria库的compose和multiple value compose函数,包括用于compose的编译器宏。你所描述的似乎与
(funcall (alexandria:compose #'h #'g #'f) x)
以致
(defun apply-funcs (functions value)
(funcall (apply #'compose (reverse functions)) value))
会做你想做的-尽管我怀疑直接调用compose可能更有效,这取决于上下文
图书馆的职能包括:
(defun compose (function &rest more-functions)
"Returns a function composed of FUNCTION and MORE-FUNCTIONS that applies its
arguments to to each in turn, starting from the rightmost of MORE-FUNCTIONS,
and then calling the next one with the primary value of the last."
(declare (optimize (speed 3) (safety 1) (debug 1)))
(reduce (lambda (f g)
(let ((f (ensure-function f))
(g (ensure-function g)))
(lambda (&rest arguments)
(declare (dynamic-extent arguments))
(funcall f (apply g arguments)))))
more-functions
:initial-value function))
(define-compiler-macro compose (function &rest more-functions)
(labels ((compose-1 (funs)
(if (cdr funs)
`(funcall ,(car funs) ,(compose-1 (cdr funs)))
`(apply ,(car funs) arguments))))
(let* ((args (cons function more-functions))
(funs (make-gensym-list (length args) "COMPOSE")))
`(let ,(loop for f in funs for arg in args
collect `(,f (ensure-function ,arg)))
(declare (optimize (speed 3) (safety 1) (debug 1)))
(lambda (&rest arguments)
(declare (dynamic-extent arguments))
,(compose-1 funs))))))
您可以通过指定:from end t:defun apply functions value reduce“funcall reverse functions:from end t:initial value”来避免显式创建包装lambda。@那么您就不需要反转函数了,对吗?这不就是reduce'funcall函数吗:从t端开始:初始值?@JoshuaTaylor:我理解首先应用第一个函数的问题。@Svante是的,你是对的。我误解了这个问题。找出哪一个代价更高是很有趣的:一个匿名函数lambda arg f funcall f arg或颠倒列表。当然,这取决于列表的大小。您可以通过指定:from end t:defun apply functions value reduce“funcall reverse functions:from end t:initial value”来避免显式创建包装lambda。@那么,您就不需要反转函数了,对吗?这不就是reduce'funcall函数吗:从t端开始:初始值?@JoshuaTaylor:我理解首先应用第一个函数的问题。@Svante是的,你是对的。我误解了这个问题。找出哪一个代价更高是很有趣的:一个匿名函数lambda arg f funcall f arg或颠倒列表。当然,这取决于名单的大小。