### Clojure Golf episode 1

This is an attempt to have some fun with Clojure. I hope to engage the Clojure community, but it would be all the more fun if others played along with their chosen language(s). The idea is that I present a sub-optimal code snippet and people throw in their optimized, smallest, and/or weirdest submissions of that same function.

Episode 1 is the function `filter-collecting`

taken directly from Greg’s Little Object System — the code is thus:

(defn filter-collecting [predicate collector & lists] (lazy-seq (loop [lists lists out []] (if (empty? (first lists)) (reverse out) (let [heads (map first lists)] (if (apply predicate heads) (recur (map rest lists) (cons (apply collector heads) out)) (recur (map rest lists) out))))))) (filter-collecting (fn [x y] (< x y)) (fn [x y] (+ x y)) ‘(1 7 3 9) ‘(5 5 5 5)) ;;=> (6 8)

In a nutshell, it takes *n* number of `lists`

and applies a `predicate`

to subsequent elements. If said predicate passes, then it applies the `collector`

function (arity *n*) and returns that result in a collection. As a starting point, it should be noted that this is a direct translation from Scheme and should be more Clojure-esque

Have fun.

## Follow-up

There were some nice follow-ups on the Clojure group (code changes only done for formatting purposes):

#### Jarkko Oranen

(remove nil?

(apply map (fn [& args]

(when (apply c args)

(apply f args)))

seqs)))

#### Christophe Grand

*my personal favorite*

(for [v (apply map vector lists)

:when (apply predicate v)]

(apply collector v)))

#### Chris Houser

(map #(apply c %)

(filter #(apply p %)

(apply map vector l))))

#### Laurent Petit

(defn filter–collecting [p c & l]

(remove #(identical? % x)

(apply map #(if (apply p %&) (apply c %&) x) l))))

;; AND

(defn filter–collecting [p c & l]

(apply mapcat

#(when (apply p %&) [(apply c %&)]) l))

#### Jonathan Smith

(let [fun #(if (apply p %1)

(conj! %2 (apply c %1))

%2)]

(loop [hs (map first seqs)

ts (map rest seqs)

result (transient [])]

(if (next (first ts))

(recur (map first ts)

(map rest ts)

(fun hs result))

(persistent! (fun hs result))))))

Thanks to everyone who participated.

-m

## 6 Comments, Comment or Ping

Ronen

Well iv made another solution (http://snipplr.com/view/18345/my-filter-collection-solution/)

My comments on the original solution:

Thanks for the challenge!

Aug 15th, 2009

Eric Normand

It’s a pretty simple function.

http://gist.github.com/169171

Aug 17th, 2009

fogus

@Ronen,

Thanks for the snippet(s). I tend to like your second solution the best for the same reason that I like Grand’s — it tells the story of its functionality. The next step would be to lose your heads. ;) I agree with all of your comments and it goes to show that although Clojure can quite easily be translated directly from Scheme, that approach is not likely to yield idiomatic results.

-m

Aug 24th, 2009

Saptarshi

Rather later in the day, but for the R language:

filter.collecting <- function(predicate, collector, …){ w <- which(mapply(predicate, …)) newl <- lapply(list(…),function(r) r[w]) newl$FUN <- collector do.call(“mapply”,newl) }

usage ::

filter.collecting(“<“,”+”, c(1,7,3,9),c(5,5,5,5))

Mar 24th, 2010

Saptarshi

Oops, the newlines disappeared, here it is again filter.collecting <- function(predicate, collector, …){

w <- which(mapply(predicate, …))

newl <- lapply(list(…),function(r) r[w])

newl$FUN <- collector

do.call(“mapply”,newl)

}

usage ::

filter.collecting(“<“,”+”, c(1,7,3,9),c(5,5,5,5))

Mar 24th, 2010

Saptarshi

Hello, I apologize for the repeated posts, this the last one for sure. A bit more space efficient:

filter.collecting <- function(predicate, collector,…){

z <- mapply(function(…) if(do.call(predicate,list(…))) do.call(collector,list(…)) ,…,SIMPLIFY=TRUE);

Filter(function(r) !is.null(r), z);

}

filter.collecting(‘<‘,’+’, c(1,7,3,9),c(5,5,5,5));

Mar 24th, 2010

## Reply to “Clojure Golf episode 1”