Common lisp 如何减少公共Lisp中的布尔值列表?
给定一个值列表,如果所有元素都不是NIL,我想将列表缩减为T,如果不是,则为NIL。这给了我一个错误:Common lisp 如何减少公共Lisp中的布尔值列表?,common-lisp,apply,reduce,Common Lisp,Apply,Reduce,给定一个值列表,如果所有元素都不是NIL,我想将列表缩减为T,如果不是,则为NIL。这给了我一个错误: (apply #'and (get-some-list)) 正如这一点: (reduce #'and (get-some-list)) 这是我想到的最好的: [11]> (defun my-and (x y) (and x y)) MY-AND [12]> (reduce #'my-and '(T T T T T)) T [13]> (reduce #'my-and
(apply #'and (get-some-list))
正如这一点:
(reduce #'and (get-some-list))
这是我想到的最好的:
[11]> (defun my-and (x y) (and x y))
MY-AND
[12]> (reduce #'my-and '(T T T T T))
T
[13]> (reduce #'my-and '(T T T T NIL))
NIL
为什么“#”和“无效”?在Common Lisp中有没有更惯用的方法来实现这一点?#”和
无效,因为和
是宏,而不是函数
通过使用lambda,您可以避免定义命名函数:
(reduce (lambda (x y) (and x y)) (get-some-list) :initial-value t)
但是,没有像#“
这样的快捷方式
或者,您也可以使用
every
,并将identify函数用作谓词。您只能在普通函数中使用'sharp quote'符号
Note that only ordinary functions can be quoted with #’. It is an error to
quote a macro function or special function this way, or to quote a symbol with
#’ if that symbol does not name a function.
> #’if
Error: IF is not an ordinary function.
您可以使用以下各项功能:
(every #'identity '(T T T T T)) -> T
(flet ((my-and (x y) (and x y)))
#'my-and)
及
可能最有效的方法是使用循环:
(loop for element in '(T T T T nil) always element) -> NIL
优点是不需要对列表元素进行函数调用
#'
是一个读取宏,它在读取表达式时展开为函数。因此,#和
是(函数和)
功能描述如下:
函数接受函数名或lambda表达式并返回相应的函数对象
定义如下:
它说的是宏,不是函数。结果是(函数和)不起作用,因为函数需要函数而不是宏来返回相应的函数对象。正如sepp2k在他的回答中所描述的,您可以使用LAMBDA创建一个函数,并在该函数中使用宏和。宏不能作为值传递,以后不能通过FUNCALL或APPLY调用。这仅适用于函数
Note that only ordinary functions can be quoted with #’. It is an error to
quote a macro function or special function this way, or to quote a symbol with
#’ if that symbol does not name a function.
> #’if
Error: IF is not an ordinary function.
此解决方案编写为
(reduce (lambda (x y) (and x y)) (get-some-list))
(reduce #'(lambda (x y) (and x y)) (get-some-list))
LAMBDA是将(LAMBDA(…)…)
扩展为(function(LAMBDA(…)…)
的宏
因此,上述内容实际上是:
(reduce (function (lambda (x y) (and x y))) (get-some-list))
可以写成
(reduce (lambda (x y) (and x y)) (get-some-list))
(reduce #'(lambda (x y) (and x y)) (get-some-list))
函数是必需的,因为Common Lisp使值和函数的命名空间有所不同。REDUCE需要将函数作为参数按值传递。所以我们需要从函数名称空间中检索函数——这是函数的目的。无论何时我们想要传递一个函数对象,我们都需要从函数名称空间获取它
例如,对于局部函数:
(every #'identity '(T T T T T)) -> T
(flet ((my-and (x y) (and x y)))
#'my-and)
LAMBDA作为一个方便的宏,在公共Lisp的设计过程中被添加到(函数(LAMBDA…)。实际上@PietroBraione您是错误的:D。如果您提供了
:initial value
标志,则不会使用一个参数调用它。这在hyperspec中是明确的:“如果子序列是空的,并且没有给出初始值,那么函数将使用零参数调用,并且reduce返回函数所做的任何操作。这是唯一一种使用两个参数以外的参数调用函数的情况。”