Thank you for your feedback and interesting ideas.
I've decided to bite the bullet and to write my own multi-filter fn.
I'm very new to Clojure so any (constructive :-) ) criticism is
welcome:

(defn multi-filter [filters coll]
  (reduce
    (fn [res e]
      (map (fn [f r] (if (f e) (conj r e) r))
        filters
        res))
    (repeat (count filters) [])
    coll
  )
)

It takes a list of filter functions and coll and returns a list of
vectors each one containing result of corresponding filter. Here is
how I use it in my context:
  (let [ ...
        [sales upgrades demo]
          (multi-filter [
              #($ % "Product Type Identifier" = "1" &&
                   % "Vendor Identifier" = "01010012"
              )
              #($ % "Product Type Identifier" = "7" &&
                  % "Vendor Identifier" = "01010012"
              )
              #($ % "Product Type Identifier" = "1" &&
                  % "Vendor Identifier" = "01010318"
              )
            ]
            (get-idata)
          )
    ]

Evaluation happens during destructuring bind (which is good for me
because idata is coming from file).
Interestingly enough replacing map with eager-map in multi-filter
definition gives very insignificant boost in perf (less than 10%), so
I've decided to leave it as is.
May be there are improvements possible to my emap definition?

(defn emap [f c1 c2]
  (loop [s1 (seq c1) s2 (seq c2) res [] ]
    (if (and s1 s2)
      (recur (seq (rest s1)) (seq (rest s2)) (conj res (f (first s1)
(first s2))))
      res)))

- Dmitry

On Oct 19, 12:13 pm, Meikel Brandmeyer <m...@kotka.de> wrote:
> 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
>
>  smime.p7s
> 3KViewDownload

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to