pos*_*ist 12 reduce common-lisp apply
给定一个值列表,如果所有元素都不是NIL,我想将列表减少到T,否则就是NIL.这给了我一个错误:
(apply #'and (get-some-list))
Run Code Online (Sandbox Code Playgroud)
就像这样:
(reduce #'and (get-some-list))
Run Code Online (Sandbox Code Playgroud)
这是我提出的最好的:
[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
Run Code Online (Sandbox Code Playgroud)
为什么"#"和"无效?在Common Lisp中有更惯用的方法吗?
Rai*_*wig 20
您可以使用EVERY函数:
(every #'identity '(T T T T T)) -> T
Run Code Online (Sandbox Code Playgroud)
和
(every #'identity '(T T T T NIL)) -> NIL
Run Code Online (Sandbox Code Playgroud)
可能最有效的方法是使用LOOP:
(loop for element in '(T T T T nil) always element) -> NIL
Run Code Online (Sandbox Code Playgroud)
优点是不需要对列表元素进行函数调用.
#'
是一个读取宏,在读取表达式时会扩展为FUNCTION.所以,#'and
是(作用).
这里描述了FUNCTION:http://www.lispworks.com/documentation/HyperSpec/Body/s_fn.htm
FUNCTION接受函数名或lambda表达式,并返回相应的函数对象.
AND在此处定义:http: //www.lispworks.com/documentation/HyperSpec/Body/m_and.htm
它说AND是一个宏,而不是一个函数.结果是(FUNCTION AND)不起作用,因为FUNCTION需要一个函数而不是一个宏来返回相应的函数对象.正如sepp2k在他的回答中所描述的那样,你可以使用LAMBDA创建一个函数,并在该函数中使用宏AND.宏不能作为值传递,以后可以通过FUNCALL或APPLY调用.这仅适用于功能.
这个解决方案写成
(reduce (lambda (x y) (and x y)) (get-some-list))
Run Code Online (Sandbox Code Playgroud)
LAMBDA是一个扩展(lambda (...) ...)
到 的宏(function (lambda (...) ...))
.
所以上面是真的:
(reduce (function (lambda (x y) (and x y))) (get-some-list))
Run Code Online (Sandbox Code Playgroud)
可以写成
(reduce #'(lambda (x y) (and x y)) (get-some-list))
Run Code Online (Sandbox Code Playgroud)
需要FUNCTION,因为Common Lisp在值和函数的命名空间之间有所区别.REDUCE需要通过值将函数作为参数传递.所以我们需要从函数命名空间中检索函数 - 这是FUNCTION的目的.每当我们想要传递一个函数对象时,我们需要从函数命名空间中获取它.
例如,在本地函数的情况下:
(flet ((my-and (x y) (and x y)))
#'my-and)
Run Code Online (Sandbox Code Playgroud)
在Common Lisp的设计过程中添加了LAMBDA作为扩展为(FUNCTION(LAMBDA ...))的便利宏.
sep*_*p2k 10
#'and
是无效的,因为它and
是一个宏,而不是一个函数.
你可以通过使用lambda来定义一个命名函数:
(reduce (lambda (x y) (and x y)) (get-some-list) :initial-value t)
Run Code Online (Sandbox Code Playgroud)
虽然没有捷径#'
.
或者,您也可以使用every
识别函数作为谓词.