Common lisp 如何减少公共Lisp中的布尔值列表?

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

给定一个值列表,如果所有元素都不是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 '(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返回函数所做的任何操作。这是唯一一种使用两个参数以外的参数调用函数的情况。”