I look for compacting expression like:
(let ( (val (complex-expr ...)) )
(or (pred1 val) (pred2 val) ...(predN val)))
Instead I like something:
(apply-some (complex-expr ...) '(pred1 pred2 ... predN))
You can use cl-some
to apply a list of predicates to a value:
(cl-some (lambda (p) (funcall p "some value"))
'(vectorp listp stringp))
I suppose you could wrap this in a function. Although I don't love this name, say:
(defun cl-emos (preds v)
"Are any PREDS true for V.
This is the \"opposite\" of `cl-some', which sees if one pred is
true for any values."
(cl-some (lambda (p) (funcall p v))
preds))
Example uses:
(cl-emos '(vectorp listp stringp)
"string")
;; => t
(cl-emos '(vectorp listp stringp)
42)
;; => nil
Note: Whatever you name it, of course you shouldn't prefix it with
cl-
. I did that just to make the comparison clear withcl-some
.
Compared to cl-some
, I prefer the way that ormap
works in Scheme and Racket: It returns the truthy value, not just t
(even when the predicate only returns t
). To do that, here, just replace (funcall p v)
with (and (funcall p v) v)
:
(defun cl-emos (preds v)
"Are any PREDS true for V.
This is the \"opposite\" of `cl-some', which sees if one pred is
true for any values."
(cl-some (lambda (p) (and (funcall p v) v)) ;; <======
preds))
(cl-emos '(vectorp listp stringp)
"string")
;; => "string"
(cl-emos '(vectorp listp stringp)
42)
;; => nil
Of course now it's subtly different than using cl-some
with the same predicate(s). But it lets you return the expensive expression's evaluated result and bind it, which seems closer to the spirit of you question.
If I understand your request OK, this is exactly what run-hook-with-args-until-success
does. (There are also functions run-hook-with-args-until-failure
and run-hook-with-args
.)
run-hook-with-args-until-success is a built-in function in `C source
code'.
(run-hook-with-args-until-success HOOK &rest ARGS)
Run HOOK with the specified arguments ARGS.
HOOK should be a symbol, a hook variable. The value of HOOK
may be nil, a function, or a list of functions. Call each
function in order with arguments ARGS, stopping at the first
one that returns non-nil, and return that value. Otherwise (if
all functions return nil, or if there are no functions to call),
return nil.
Do not use ‘make-local-variable’ to make a hook variable buffer-local.
Instead, use ‘add-hook’ and specify t for the LOCAL argument.
See the Elisp manual, node Running Hooks.
I don't know of an existing function to do this, but it's simple enough to write in plain Elisp.
(defun some-predicate (val predicates)
(when predicates
(or (funcall (car predicates) val)
(some-predicate val (cdr predicates)))))
This returns t
(the return value of the predicate that returns non-nil):
(some-predicate 1 '((lambda (val) (> val 2)) (lambda (val) (> val 0))))
This returns nil
:
(some-predicate 1 '((lambda (val) (> val 2)) (lambda (val) (> val 1))))
Note that because it uses recursion, it could blow the stack if you have a long list of predicates.
With help from https://stackoverflow.com/a/32690256/173149 there are another built-in into cl-lib
alternatives which also available in CL:
;; analog for some.
(loop with value = (floor (* 10 (sin 9)))
for pred in (list #'symbolp #'numberp)
thereis (funcall pred value))
;; analog for every.
(loop with value = (floor (* 10 (sin 9)))
for pred in (list #'numberp #'plusp #'evenp)
always (funcall pred value))
-some->
, except that you need to invert the predicates. But I don't know of any function that'd do it in standard library, so writing one yourself doesn't sound like a bad idea. Perhaps you could suggest this as a feature to Dash library maintainers. – wvxvw Sep 19 '15 at 16:46