I want to do something like this:
class Foo extends Ordered[Foo] {
val x
val y
val z
.
.
.
.
def compare(that: Foo) = {
val c0 = this.length compareTo that.length // primary comparison
lazy val c1 = this.x compareTo that.x // secondary comparison
lazy val c2 = this.y.size compareTo that.y.size // tertiary comparison
lazy val c3 = this.z.head compareTo that.z.head // final tie breaker
if (c0 != 0) c0 else if (c1 != 0) c1 else if (c2 != 0) c2 else if (c3 != 0) c3 else c4
}
}
I was wondering if there was any cleaner way to write this kind of thing. I am expecting some thing like Ordering.multipleBy(ordering: Ordered[A]*) signature which takes a varargs of comparables and selects first non zero.
It is often better to use
Orderinginstead ofOrdered.Orderingis a type class and is much more flexible thanOrdered(if only becauseOrderedmust be implemented by the type to compare, while withOrderingyou can define this outside). To define the natural ordering (defaultOrderinginstance) for your type, you just define an implicit ordering value in the companion object.So, enough with the preamble. The nice thing is that when using
Orderingwhat you want to do is pretty simple, as there is an implicit ordering for tuples (provided that the tuple elements themselves have a orderings)`:In addition, there is an implicit conversion that converts any value that has an
Orderingtype class instance into anOrderedvalue (seeOrdered.orderingToOrdered) so we have nothing special to do to automagically being able to pass any instance ofFooto a function that expects anOrdered[Foo])UPDATE: Concerning your new question:
One way to do it would be to use mostly the same technic based on
Ordering.byand conversion to tuples, but explicitly passing the orderings to compose:But it is relatively “noisy”.
I could not find anything better using only the standard library, and so I would actually advise to use our own helper:
Which can be used like this:
Or even simpler, like this:
CompositeOrdering.applyis basically what you calledOrdering.multipleByin your question.