Hi Mark,
Not sure if this is better but here is another way to do it.
(defn simple-build-coll [a b]
(vec
(filter #(not (nil? %))
(list
(when (> a 2) (* a b))
(when (> b 2) (+ a b))
(when (> a b) (- a b))))))
user=> (simple-build-coll 3 1)
[3 2]
The vec is just to convert the collection to a vector if
thats whats being used.
If this is commonly needed in the program I would probably write
a macro to do this. Its would make the program much more
readable .. not the macro but the usage of it :)
(defn reverse-pairs [l]
(apply concat (reverse (partition 2 l))))
(defmacro conj-if-aux [coll & preds_xs]
(if preds_xs
`(if ~(first preds_xs)
(conj (conj-if-aux ~coll ~@(rest (rest preds_xs))) ~(second
preds_xs))
(conj-if-aux ~coll ~@(rest (rest preds_xs))))
coll))
(defmacro conj-if [coll & preds_xs]
`(conj-if-aux ~coll ~@(reverse-pairs preds_xs)))
The main logic is in conj-if-aux.
I use reverse-pairs and conj-if just to maintain the
correct order in the resulting collection (for lists and vectors).
If thats not important conj-if-aux should suffice.
reverse-pairs maintains the pairs of predicate and exprs
in the reversed list.
user=> (reverse-pairs [:a :b :c :d :e :f])
(:e :f :c :d :a :b)
Usage would be:
(defn mac-build-coll [a b]
(conj-if [9 10]
(> a 2) (* a b)
(> b 2) (+ a b)
(> a b) (- a b)))
(defn mac-build-coll2 [a b]
(conj-if '(9 10)
(> a 2) (* a b)
(> b 2) (+ a b)
(> a b) (- a b)))
user=> (mac-build-coll 3 1)
[9 10 3 2]
user=> (mac-build-coll2 3 1)
(2 3 9 10)
user=>
Note that (1) the type of collection is maintained by
conj here (either a list or a vector) and (2) the order in
which elements are added depend on the the type of collection.
Conj appends to head of list.
9,10 are used for the initial collection (either vector or list).
Parth
>
> Thanks,
> - Mark McGranaghan