简体   繁体   中英

Combine functions for same collection

I just start learning Clojure , and I get used in other functional language create some pipelines with functions like

val result = filter(something)
             map(something)
             reduce(something)
         collection

I'm trying to achieve something like that with Clojure combining two filter functions

(defn filter-1 [array] (filter
                         (fn [word] (or (= word "politrons") (= word "hello"))) array))
(defn filter-2 [array] (filter
                         (fn [word] (= word "politrons")) array))

(def result (filter-1 ["hello" "politrons" "welcome" "to" "functional" "lisp" ""]))

(println "First:" result)

(println "Pipeline:" ((filter-2 result)))

But I'm unable to make it works.

Could you please can provide some advice or documentation of how to combine two predicate functions for a same collection ?

Regards

Your two filter-$ functions are fully fledged already (Note, that you would gain more re-usability by making your predicates functions and not the whole filtering with the predicate hidden).

So to make that work, you can go with the thread-last macro ->> :

(->> array
     filter-1
     filter-2)

This is a rather general approach, you will see often in code in the wild. More general:

(->> xs
     (filter pred?)
     (map tf)
     (remove pred?))

The newer approach for this are transducers , where the combination is done via comp . And this would also be the way to actually combine your whole transformation pipeline into a new function.

Eg

(def my-xf
 (comp 
   (filter pred1)
   (filter pred2)))

(into [] my-xf xs)

Note the use of the single argument version on filter .

there are some options to compose processing steps:

you can just pipeline filter calls like this:

   (->> data
        (filter #{"politrons" "hello"})
        (filter #{"politrons"}))
   ;;=> ("politrons")

notice these word sets to be used as filter functions (just a shortcut for those equality predicates of yours)

but i guess what you need to know, is the transducers concept, since it's usages include (but not limited to) this type of pipelining you need:

(eduction (filter #{"politrons" "hello"})
          (filter #{"hello"})
          data)
;;=> ("hello")

in case you just need filtering, you can also combine filter function with higher-level functions like every-pred :

(filter (every-pred #{"politrons" "hello"}
                    #(= "olleh" (clojure.string/reverse %)))
        data)
;;=> ("hello")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM