Hi,

Clojure is great! The gain in productivity from more low level
languages like Java, but also more functional languages like Ruby and
Common LISP etc. amazes me every day. Like how adding a simple "map"
in front of the count here:
(count colls)
changes the code from counting the number of collections to
enumerating the number of items in those collections. It's all these
little things that take one minute or 5 in Java, but only 5 seconds in
Clojure (in case you are a slow typer) that make you so much more
efficient. With clojure, I spend most of my time thinking about
problems at a conceptual level, rather than at the implementation
level (Java: int[] vs. Iterable<Integer> vs. List<Integer> vs.
Integer[] etc. - arrg!). Thanks Rich!

That said, every now and then I come across a function in clojure.core
that could be vastly improved in its range of applicability by just
adding one or more optional parameters, defaulting to the currently
hard-coded values (like the often implicit 'identity' function). Take
'distinct'. I'd like to be able to specify the keyfn, that's an
important one for me, and while we're at it, I'd like to pass in the
set that that function builds up incrementally, and normally starts
with an empty set, so that I can pre-initialize it, say with #{ nil },
so that it also filters out nils.

This 2nd point is not that important, and I'm not sure if it is that
great an idea in terms of "orthogonality" of the functions, as we have
filter. But you'd get rid off one level of indirection. distinct
basically gives us a filter for free.

But the 1st point I think certainly makes sense, and we have a couple
of other fns in clojure that have a variant with a keyfn parameter,
like sort-by etc. I guess they normally get a different name.

I'm not so sure about what the best order of parameters is in clojure,
and named parameters would make this a no brainer, but this is what I
currently use, the first parameter being coll, at least in the variant
with only one parameter that makes it a drop-in replacement candidate
for distinct:

(defn distinkt
  "Returns a lazy sequence of the elements of coll with duplicates
removed"
  ([coll] (distinkt coll identity))
  ([coll keyfn] (distinkt coll keyfn #{}))
  ([coll keyfn seen-items]
    (let [step (fn step [xs seen]
                   (lazy-seq
                    ((fn [[f :as xs] seen]
                      (when-let [s (seq xs)]
                        (let [key (keyfn f)]
                              (if (contains? seen key)
                                (recur (rest s) seen)
                                (cons f (step (rest s) (conj seen key)))))))
                      xs seen)))]
      (step coll seen-items))))

I don't mind writing - or better - copy-and-pasting this code and
keeping it in my project, but I think it could be useful for others,
so I wouldn't mind at all if this makes it into clojure.core... :)

Or is the reason for hard coding an (implicit) 'identity' performance?
Or did I miss some other way to achieve the same goal?

Eugen

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to