I seem to recall Rich saying "I like the destructuring part of pattern
matching." In my efforts to appreciate that statement, I am playing
around with porting simple Haskell examples to Clojure, trying to use
destructuring (and multimethods) where the Haskell does pattern matches.
For example:
-- Haskell
qsort [] = []
qsort (x:xs) = qsort smaller ++ [x] ++ qsort bigger
where smaller = filter (<x) xs
bigger = filter (>=x) xs
; Clojure, destructuring pivot and vals
(defn quicksort-1 [[pivot & vals]]
(if pivot
(let [smaller (partial filter #(< % pivot))
bigger (partial filter #(>= % pivot))]
(lazy-cat (quicksort-1 (smaller vals)) [pivot] (quicksort-1
(bigger vals))))
nil))
; Clojure again, using multimethod to separate base and recur
(defmulti quicksort-2 first)
(defmethod quicksort-2 nil [_] nil)
(defmethod quicksort-2 :default [[pivot & vals]]
(let [smaller (partial filter #(< % pivot))
bigger (partial filter #(>= % pivot))]
(lazy-cat (quicksort-2 (smaller vals)) [pivot] (quicksort-2
(bigger vals)))))
I am confident that the Clojure could be prettier, but not sure how.
Suggestions?
Cheers,
Stuart
Hi all,
I seem to recall Rich saying "I like the destructuring part of pattern
matching." In my efforts to appreciate that statement, I am playing
around with porting simple Haskell examples to Clojure, trying to use
destructuring (and multimethods) where the Haskell does pattern matches.
For example:
-- Haskell
qsort [] = []
qsort (x:xs) = qsort smaller ++ [x] ++ qsort bigger
where smaller = filter (<x) xs
bigger = filter (>=x) xs
[...]
I am confident that the Clojure could be prettier, but not sure how.
Suggestions?
Here's a variadic version:
(defn qsort
([] [])
([x & xs] (concat (apply qsort (filter #(< % x) xs))
(cons x (apply qsort (filter #(>= % x) xs))))))
user> (qsort 1234 56 789 0)
(0 56 789 1234)
Kind regards,
achim
Thanks! I like quicksort-4. It all fixes a problem that bugged me in
all the other examples, which is that "bigger" is a lie. The real
semantic is "not smaller", which quicksort-4 captures perfectly.
I will have to get used to thinking of "remove" as the opposite of
"filter." The English connotations of the former are too imperative
for me, but I don't know a better word for it.
Stuart
Nice--I like this one, except for needing to apply. What I really want
is arity overloading *within* the first argument, which is what led me
down the path to multimethods.
Is there a reason to prefer concat over lazy-cat here?
Cheers,
Stuart
Am 20.10.2008 um 20:00 schrieb Stuart Halloway:
> Nice--I like this one, except for needing to apply. What I really want
> is arity overloading *within* the first argument, which is what led me
> down the path to multimethods.
Yes, sadly arity matching is only available at the top level, so
applying was the only way to closely translate the Haskell version i
could see.
What are your concerns re: apply? Are there performance issues? Or is
it not being able to call qsort on a collection directly?
> Is there a reason to prefer concat over lazy-cat here?
No, that was entirely unintentional - sorry for the confusion.
Kind regards,
achim
I just want the code to look pretty, no deeper concerns than that. :-)