Clojure Golf, episode 1

91 views
Skip to first unread message

Fogus

unread,
Aug 14, 2009, 3:43:25 PM8/14/09
to Clojure
Wanna play golf?

(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)))))))

;; usage:
;; (filter-collecting
;; (fn [x y] (< x y))
;; (fn [x y] (+ x y))
;; '(1 7 3 9)
;; '(5 5 5 5))
;; ==> (6 8)

More detail at: http://blog.fogus.me/2009/08/14/clojure-golf-episode-1/

-m

Sean Devlin

unread,
Aug 14, 2009, 3:51:18 PM8/14/09
to Clojure
I'd start with you usage docs

;; usage:
;; (filter-collecting
;; (fn [x y] (< x y))
;; (fn [x y] (+ x y))
;; [1 7 3 9]
;; [5 5 5 5])
;; ==> (6 8)

Jarkko Oranen

unread,
Aug 14, 2009, 4:22:27 PM8/14/09
to Clojure


On Aug 14, 10:51 pm, Sean Devlin <francoisdev...@gmail.com> wrote:
> I'd start with you usage docs
>
> ;; usage:
> ;; (filter-collecting
> ;;   (fn [x y] (< x y))
> ;;   (fn [x y] (+ x y))
> ;;   [1 7 3 9]
> ;;   [5 5 5 5])
> ;;  ==> (6 8)

;; usage:
;; (filter-collecting < +
;; [1 7 3 9]
;; [5 5 5 5])
;; ==> (6 8)

(defn filter-collecting [c f & seqs]
(remove nil?
(apply map (fn [& args] (when (apply c args)
(apply f args)))
seqs)))

--
Jarkko

Chouser

unread,
Aug 14, 2009, 4:23:16 PM8/14/09
to clo...@googlegroups.com
On Fri, Aug 14, 2009 at 3:43 PM, Fogus<mef...@gmail.com> wrote:
>
> Wanna play golf?

Yes I do!

(defn filter-collecting [p c & l]
(remove nil? (apply map #(when % (apply c %&)) (apply map p l) l)))

But that gives incorrect results if c ever returns nil, so
I guess it should be:

(defn filter-collecting [p c & l]
(let [x `x#]
(remove #(= % x)
(apply map #(if % (apply c %&) x)
(apply map p l)
l))))

But that's getting pretty ugly, so maybe this is better:

(defn filter-collecting [p c & l]
(map #(apply c %)
(filter #(apply p %)
(apply map vector l))))

Nothing terribly inventive there. I'll have to get my
satisfaction from being first. I'm sure the best are yet to
come...

--Chouser

Christophe Grand

unread,
Aug 14, 2009, 5:03:47 PM8/14/09
to clo...@googlegroups.com
(defn filter-collecting [predicate collector & lists]
  (for [v (apply map vector lists) :when (apply predicate v)] (apply collector v)))
--
Professional: http://cgrand.net/ (fr)
On Clojure: http://clj-me.blogspot.com/ (en)

Laurent PETIT

unread,
Aug 14, 2009, 5:13:42 PM8/14/09
to clo...@googlegroups.com
Let's play !

First:
Slight variation on Chouser's second version (presuming it should be faster for the token comparison, which is evil - presuming performance instead of testing it ! ) :


(let [x (Object.)]

   (defn filter-collecting [p c & l]
      (remove #(identical? % x)
        (apply map #(if (apply p %&) (apply c %&) x) l))))

Second:
Very short, certainly not (?) as efficient:
(defn filter-collecting [p c & l] (apply mapcat #(when (apply p %&) [(apply c %&)]) l))


2009/8/14 Chouser <cho...@gmail.com>

Jonathan Smith

unread,
Aug 14, 2009, 6:44:14 PM8/14/09
to Clojure
On Aug 14, 3:43 pm, Fogus <mefo...@gmail.com> wrote:
> Wanna play golf?

ok...
Not efficient or elegant, but certainly weird...

(defn filter-collecting [p c & seqs]
(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))))))

Fogus

unread,
Aug 14, 2009, 9:42:39 PM8/14/09
to Clojure
> (defn filter-collecting [predicate collector & lists]
>   (for [v (apply map vector lists) :when (apply predicate v)] (apply
> collector v)))

This is very nice. It's short, sweet, and actually describes the
functionality.

-m

Fiverr Me

unread,
Jul 8, 2023, 7:43:26 AM7/8/23
to Clojure
The code snippet you provided is written in Clojure, a dialect of Lisp. The function filter-collecting takes a predicate function, a collector function, and multiple lists as arguments. It filters the lists based on the predicate function and collects the values from the corresponding positions in the lists using the collector function. Copied from https://fiverrme.com/

(filter-collecting
  (fn [x y] (< x y))      ; predicate function: checks if x < y
  (fn [x y] (+ x y))      ; collector function: adds x and y
  '(1 7 3 9)              ; first list
  '(5 5 5 5))             ; second list

The first list is (1 7 3 9) and the second list is (5 5 5 5). The function checks if each corresponding pair of elements from the two lists satisfies the predicate function (x < y). In this case, the pairs (1 5) and (3 5) satisfy the predicate because 1 is less than 5 and 3 is less than 5.

For the pairs that satisfy the predicate, the collector function (+) is applied to the corresponding elements. The sum of (1 5) is 6, and the sum of (3 5) is 8.

Therefore, the result of (filter-collecting (fn [x y] (< x y)) (fn [x y] (+ x y)) '(1 7 3 9) '(5 5 5 5)) is (6 8).
Reply all
Reply to author
Forward
0 new messages