给定值列表,如果所有元素不是零,我想将列表减少到t,如果不是,则零。这给了我一个错误:

(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

为什么“#”和“”无效?是否有一种更惯用的方法可以在共同的LISP中做到这一点?

有帮助吗?

解决方案

#'and 无效,因为 and 是宏,而不是函数。

您可以通过使用lambda来定义命名函数:

(reduce (lambda (x y) (and x y)) (get-some-list) :initial-value t)

没有快捷方式 #' 尽管。

或者,您也可以使用 every 以识别功能为谓词。

其他提示

您可以使用每个功能:

(every #'identity '(T T T T T))  ->  T

(every #'identity '(T T T T NIL))  ->  NIL

最有效的方法可能是使用循环:

(loop for element in '(T T T T nil) always element)  ->  NIL

优势是,不需要列表元素的函数调用。

#' 是一个读取宏,可以在读取表达式过程中扩展到函数。所以 #'and IS(功能和)。

功能在这里描述: http://www.lispworks.com/documentation/hyperspec/body/s_fn.htm

函数获取函数名称或lambda表达式,并返回相应的函数对象。

并在这里定义: http://www.lispworks.com/documentation/hyperspec/body/m_and.htm

它说这是宏,而不是函数。结果是(函数和)不起作用,因为功能需要一个函数而不是宏来返回相应的功能对象。正如Sepp2k在他的答案中所描述的那样,您可以使用lambda创建一个函数,并使用宏和内部功能。宏无法作为值传递,后来通过funcall或申请调用。这仅适用于函数。

该解决方案被写成

(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))

需要函数,因为常见的LISP在值和函数的名称空间之间有所不同。减少需求将函数作为参数按值传递。因此,我们需要从功能名称空间中检索函数 - 这是函数的目的。每当我们想传递函数对象时,我们都需要从函数名称空间中获取它。

例如,在本地函数的情况下:

(flet ((my-and (x y) (and x y)))
  #'my-and)

LAMBDA作为便利宏,在公共LISP的设计期间添加了扩展到功能(lambda ...))。

您只能使用普通功能使用“尖锐的引号”符号。

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.

常见的LISP:符号计算的温和介绍,第202页

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top