Reputation: 20670
In closure, how can we apply and
or any other macro to a list?
This doesn't work:
(apply and '(true false))
Because apply
can't take value of a macro.
So, what is the best way to check if all the elements of a list are true?
Upvotes: 23
Views: 5416
Reputation: 1
user=> (eval `(and ~@(list true false)))
false
user=> (eval `(and ~@ (list true true 1)))
1
I am syntax-quoting and then applying a big sledge hammer to remove the brackets around the collection and since I quoted it, have to use eval. This is useful if you are creating a macro and the function passed in is 'and'.
so (list 1 2 3)
sledge hammered becomes 1 2 3
.
This is one way, extremely terrible, but it works, so I got that going for me which is nice. So my clojure isn't great but I hope this macro example clears things up.
(defmacro split-my-args-then-apply-fn
"This is one terrible macro designed to show the use of 'and'."
[fun coll & args]
`(~fun ~@((apply juxt args) coll)))
Usage (Never):
(split-my-args-then-apply-fn
and
{:something :true :something-else false}
:something :something-else)
Upvotes: 0
Reputation: 91534
In Clojure macros are not first class things they don't compose quite like functions, and you cant pass them to other functions, and you can't apply
them. This is because they are finished and done with before any of the applying would be done.
It is customary to wrap macros in functions to apply
or pass them to functions
(defmacro my-macro [x y z] ...)
(apply #(my-macro %1 %2 %3) [1 2 3])
(map #(my-macro) [1 2 3] [:a :b :c] [a b c])
the anonymous-function reader macro #(
makes this so easy that macroes not being first class is really not an inconvenience. Just do try to remember the first rule of macro club
Upvotes: 7
Reputation: 22830
You can do this instead:
(every? identity '(true false))
See this thread for more information.
Upvotes: 38