(defn sorted?
"Sees if the sequence passed to it is sorted by key k according to function f"
([comp-fn k coll]
(if (empty? coll)
true)
(sorted? comp-fun k (get (first coll) k) (rest coll)))
([comp-fun k value coll]
(cond
(empty? coll)
true
(fun value (get (first coll) k))
(sorted-by? comp-fn k (get (first coll) k) (rest coll))
:else false)))
This code wants to grow up one day and be wrapped in another function
which will be a component (after I learn the proper use of recur), but
for now I need to understand a few things:
First, it seems the comparison operators in Clojure are less generic
than I hoped. <= and >= are only for numerical operations. That means
no strings and no other objects (like dates). Thoughts on this?
Conditionals? Multimethods? Abandon all hope?
The second problem is I don't know how (or if it's possible) to pass a
key that's not yet defined as such, as in :foo - because that symbol
doesn't yet resolve. I'm not sure about this as an issue either.
Thoughts?
Thirdly, how do other people handle not running into variable names
used by the core?
I've hit that several times today and looking for coping strategies others use.
- Serge
There's `compare', http://clojure.org/api#toc150
> The second problem is I don't know how (or if it's possible) to pass a
> key that's not yet defined as such, as in :foo - because that symbol
> doesn't yet resolve. I'm not sure about this as an issue either.
> Thoughts?
Doesn't it just return nil? (get {} :foo) -> nil, (get {} :foo :bar)
-> :bar. {:foo nil} and {} will be equal though, but that probably
makes sense.
I'm refreshing my clojure memory, so I took a stab at different kind
of `sorted?'
(defn sorted-coll?
"Is collection sorted by k according to f?"
([comp-fn k coll]
(every? #(apply comp-fn %) (partition 2 1 (map k coll)))))
Cheers,
Philip
Java has a "Comparable" interface that classes can implement for
ordering. The interface has a "compareTo" method that needs to be
implemented by the class in question. You can find out about it at http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Comparable.html
.
Classes such as Date and String implement Comparable, so you can do:
user=> (.compareTo "a" "b")
-1
Using this, you could write a more friendly interface like:
user=> (defn gt [a b] (> (.compareTo a b) 0))
#'user/gt
user=> (gt "foo" "bar")
true
----
For a Sorted? component, I think Mike was alluding to creating a
generic predicate wrapper component that can be instantiated with any
predicate, right Mike? We could do the same with filters.
----
For a Sorted? component or the like, would we possibly want to make
the flow even finer grained, and have a component called accumulator
or something like that, that would accumulate all the records into a
list, and pass that list to Sorted? as a single record? Then the
bounds of the list would be decided by the accumulator, and that would
be more modular and cohesive. We might want multiple sorted groups in
a single flow, no? Or am I going too far?
----
By the way, the Commons Lang (http://commons.apache.org/lang/api-release/index.html
) and Commons Collections (http://commons.apache.org/collections/api-release/index.html
) libraries could at some point be useful. Commons Lang has a lot of
utilities (String, System, Word, Number, StringEscape). Commons
Collections has collections related utilities and also defines
Closure, Transformer, and Predicate classes that make Java a little
less awful (though we'd probably rarely need to implement these on the
Java side).
- Keith
Nice...
- Serge
Comparable seems nice in that it tells you the ordering.
Sadly this function doesn't work with it out of the box because we're
only looking at one thing at a time, and -1 is truthy!
Still I'm extremely impressed by the density of the function.
- Serge
So maybe you can come up with a nice way to wrap compare in the larger
function. The best way I found so far is to look at the first
comparison that's non-zero and then all the subsequent compares must
be that or zero (eg if it's -1, the next one must be either -1 or 0).
The idea would be a function which can return, similarly, a -1 0 or 1,
with 0 being that the function is unsorted- then that gets wrapped in
a function that returns it as:
{:sorted "Unsorted"}
But I can't think of a really nice (read highly clever or efficient)
way to do that.
- Serge