filter+ filters several collections in parallel. Its predicate receives corresponding elements from each collection, and an element position survives when the multi-argument predicate returns a truthy value. section 3.5.3
The function has two useful forms:
- (filter+ pred coll) delegates directly to filter for one collection. section 3.5.3
- (filter+ pred c1 c2 & colls) combines corresponding values from the collections, applies pred to each group, and filters those groups. section 3.5.3
- The result is lazy; the predicate should preferably be free of side effects because lazy evaluation does not guarantee once-only predicate calls. section 3.5.3
- The implementation walks collections position by position and stops when any collection has no remaining element. section 3.5.3
Matching regular expressions against strings
(filter+ re-seq (map re-pattern (map str (range))) ["234983" "5671" "84987"]) ;; ((#"1" "5671")) Each regular expression is paired with the string at the same position. Only the pair whose predicate result is truthy remains. section 3.5.3
(defn walk-all
"Returns a lazy-seq of all first elements in coll,
then all second elements and so on."
[colls]
(lazy-seq
(let [ss (map seq colls)] ; #1
(when (every? identity ss) ; #2
(cons (map first ss) (walk-all (map rest ss))))))) ; #3
(defn filter+
([pred coll] ; #4
(filter pred coll))
([pred c1 c2 & colls] ; #5
(filter+ #(apply pred %) (walk-all (conj colls c2 c1)))))
Inspect the implementation to see the single-collection delegation, parallel traversal, and predicate application. section 3.5.3
