My apologies for misrepresenting Haskell's nubBy:
On 22 February 2010 19:15, Michał Marczyk <[email protected]> wrote:
> The Haskell approach is to have two functions, nub and nubBy, which
> perform the task of distinct and the task of distinct with a
> user-provided keyfn, respectively.
Actually nubBy takes a binary function as its first argument and
performs equality comparisons of each successive element to each of
the elements collected into the result list using that function. A
corresponding Clojure function:
(defn distinct-by
"A version following Haskell's nubBy."
[f coll]
(let [step (fn step [xs seen]
(lazy-seq
((fn [[x :as xs] seen]
(when-let [s (seq xs)]
(if (some #(f x %) seen)
(recur (rest s) seen)
(cons x (step (rest s) (conj seen x))))))
xs seen)))]
(step coll #{})))
Here's one example of use:
user> (distinct-by #(= (class %1) (class %2)) [1 2 3 :a :b :c 'a 'b 'c])
(1 :a a)
And here's a Clojure version of the coolest Haskell one-liner I've ever seen:
user> (take 10 (distinct-by #(< 1 (gcd %1 %2)) (iterate inc 2)))
(2 3 5 7 11 13 17 19 23 29)
The alternative is to use a unary keyfn-based approach as I originally
suggested. This would work like so:
(defn distinct-by
"NB. this isn't like Haskell's nubBy. f is supposed to be unary."
[f coll]
(let [step (fn step [xs seen]
(lazy-seq
((fn [[x :as xs] seen]
(when-let [s (seq xs)]
(if (some #(f x %) seen)
(recur (rest s) seen)
(cons x (step (rest s) (conj seen (f x)))))))
xs seen)))]
(step coll #{})))
user> (distinct-by class [1 2 3 :a :b :c 'a 'b 'c])
(1 :a a)
Now I'm not really sure which one is more deserving of being called
distinct-by...
Sincerely,
Michał
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en