如何将"或"应用于elisp中的列表

Epo*_*ous 21 lisp elisp

在elisp我可以评估或作为一个函数就像+.

(or nil 0 nil) ==> 0

(+ 1 0 1) ==> 2
Run Code Online (Sandbox Code Playgroud)

我可以使用apply来将+应用到列表中

(apply '+ '(1 0 1)) ==> 2
Run Code Online (Sandbox Code Playgroud)

所以,我会想或者会以同样的方式工作,但事实并非如此.

(apply 'or '(nil 0 nil)) ==> error: (invalid-function or)
Run Code Online (Sandbox Code Playgroud)

我想这是来自用于实现短路评估的一些内部魔术.如何使用apply对列表执行或操作?


PS我想要的应用程序是找出命令行上的任何元素是否与特定模式匹配,所以我写的重要部分是:

(apply 'or (mapcar (lambda (x) (string-match-p "pattern" x)) command-line-args))
Run Code Online (Sandbox Code Playgroud)

但它不起作用

Eli*_*lay 21

问题在于它or是一个宏(这是所讨论的"内部魔法"),你说得对,它可以做短路.如果or是一个函数,那么调用它将需要遵循用于评估函数调用的通常规则:在调用之前需要对所有参数进行求值.

另请参阅这个问题 - 它是关于Scheme的,但它是完全相同的问题.

至于解决方案,您应该使用some,如:

(some (lambda (x) (string-match-p "pattern" x)) command-line-args)
Run Code Online (Sandbox Code Playgroud)

注意:这使用默认情况下未包含在emacs中的常见lisp.只是用(require 'cl)


Ken*_*Ken 10

如果它让你感觉更好,那你就是一个好伙伴!这是Lisp FAQ的"常见陷阱"部分中的第三个问题:

这是简单但不一定令人满意的答案:AND和OR是宏,而不是函数; APPLY和FUNCALL只能用于调用函数,而不能用于调用宏和特殊运算符.

...... Eli当然正确地使用了他的建议SOME:

Common Lisp函数EVERY和SOME可用于在尝试应用#'AND和#'OR时获得您想要的功能.

(FAQ和这个答案主要是关于Common Lisp,但在这种情况下,如果省略#字符,答案是相同的.)