Search code examples
lispelisp

How do I apply "or" to a list in elisp


In elisp I can evaluate or as a function just like +.

(or nil 0 nil) ==> 0

(+ 1 0 1) ==> 2

I can use apply to apply + to a list

(apply '+ '(1 0 1)) ==> 2

So, I would think or would work the same way, but it doesn't.

(apply 'or '(nil 0 nil)) ==> error: (invalid-function or)

I imagine this comes from some internal magic used to implement the short-circuit evaluation. How can I use apply to execute the or operation over a list?


P.S. my desired application is to find out whether any elements on the command line match a particular pattern, so the important part of what I am writing is:

(apply 'or (mapcar (lambda (x) (string-match-p "pattern" x)) command-line-args))

But it doesn't work


Solution

  • The problem is that or is a macro (which is the "internal magic" in question), and you're right that that's done so it can do short-circuiting. If or was a function, then calling it would need to follow the usual rules for evaluating a function call: all the arguments would need to get evaluated before the call is made.

    See also this question -- it's about Scheme but it's the exact same issue.

    As for a solution, you should probably use some, as in:

    (some (lambda (x) (string-match-p "pattern" x)) command-line-args)
    

    Note: this uses common lisp that is not included in emacs by default. Just use (require 'cl)