viebel
viebel

Reputation: 20670

In clojure, how to apply 'and' to a list?

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

Answers (4)

Dhruv
Dhruv

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

Fei Meng
Fei Meng

Reputation: 79

You can also do this: (apply = true '(true false))

Upvotes: 5

Arthur Ulfeldt
Arthur Ulfeldt

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

Kai Sternad
Kai Sternad

Reputation: 22830

You can do this instead:

(every? identity '(true false))

See this thread for more information.

Upvotes: 38

Related Questions