Reputation: 5504
This question similar to say, In clojure, how to apply 'and' to a list?, but solution doesn't apply to my question. every?
function returns just a boolean value.
or
is a macro, so this code is invalid:
(apply or [nil 10 20]) ; I want to get 10 here, as if 'or was a function.
Using not-every?
I will get just boolean value, but I want to preserve semantics of or
- the "true" element should be a value of the expression. What is idiomatic way to do this?
My idea so far:
(first (drop-while not [nil 10 20])) ; = 10
Upvotes: 3
Views: 545
Reputation: 9266
A simple macro:
(defmacro apply-or
[coll]
`(or ~@coll))
Or even more abstract
(defmacro apply-macro
[macro coll]
`(~macro ~@coll))
EDIT: Since you complained about that not working in runtime here comes a version of apply-macro that works in runtime. Compare it with answers posted here: In clojure, how to apply a macro to a list?
(defmacro apply-macro-in-runtime
[m c]
`(eval (concat '(~m) ~c)))
Notice that this version utilizes that parameters are passed unevaluated (m is not evaluated, if this was a function, it would throw because a macro doesn't have a value) it uses concat
to build a list containing of a list with the quoted macro-name and whatever the evaluation of form c (for coll) returns so that c as (range 5)
would be fully evaluated to the list that range
returns. Finally it uses eval
to evaluate the expression.
Clarification: That obviously uses eval which causes overhead. But notice that eval was also used in the answer linked above.
Also this does not work with large sequences due to the recursive definition of or
. It is just good to know that it is possible.
Also for runtime sequences it makes obviously more sense to use some
and every?
.
Upvotes: 3