Hi,

Am 19.10.2009 um 01:34 schrieb Dmitry Kakurin:

> This is in line with what I was thinking for my own custom filter
> function.
> Now how would you modify it if the same record can be both "sales" and
> "upgrade" at the same time?
> I.e. if filters are not mutually exclusive.

I'd define a helper. (Code untested)

(defmacro ->if
   "Acts like ->, but pipes the expression only through the next step
   if the predicate clause returns true. Otherwise it skips the step
   going on with the next steps, if any."
   ([x] x)
   ([x pred form & forms]
    (let [x-gs (gensym "x")]
      `(let [~x-gs ~x]
         (if (-> ~x-gs ~pred)
           (-> ~x-gs form (->if ~...@forms))
           (->if ~x-gs ~...@forms))))))

(letfn [(add-sale
           [[sales upgrades demos] x]
           [(conj sales x) upgrades demos])
         (add-upgrade
           [[sales upgrades demos] x]
           [sales (conj upgrades x) demos])
         (add-demo
           [[sales upgrades demos] x]
           [sales upgrades (conj demos x)])]
   (reduce (fn [sales-upgrades-demos data]
             (->if sales-ugprades-demos
               (do (is-sales? data))   (add-sale data)
               (do (is-upgrade? data)) (add-upgrade data)
               (do (is-demo? data))    (add-demo data)))
           [[] [] []] (get-idata)))

This is maybe trying to be a little too clever, but well... I found  
something like ->if useful at times. Note that, the predicate there  
normally depends on the thing piped through the chain with ->. However  
in our case it is not. That's what's the do is for: to ignore the  
argument of the ->.

Looking at this, I would think, that the other approaches using the  
group are much more elegant.

Hmm.. Another approach might be juxt:

(defn conj-if
   "Conjoins x to coll if x fulfills pred."
   [pred coll x]
   (if (pred x)
     (conj coll x)
     coll))

(reduce (juxt #(conj-if is-sales? (nth %1 0) %2)
               #(conj-if is-upgrade? (nth %1 1) %2)
               #(conj-if is-demo? (nth %1 2) %2))
         [[] [] []] (get-idata))

This looks much nicer, although there is still the ugly nth  
"destructuring" for vector. And juxt is maybe only semi-official API  
at the moment... If you don't want to depend on contrib, this might be  
an alternative, though...

Sincerely
Meikel

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to