I'm switching from scala 2.7 and ordered to scala 2.8 and using ordering. It looks quite straight forward but I was wondering could I make it a little less verbose. For example:
scala> case class A(i: Int)
defined class A
scala> object A extends Ordering[A] { def compare(o1: A, o2: A) = o1.i - o2.i}
defined module A
If I then try to create a TreeMap I get an error
scala> new collection.immutable.TreeMap[A, String]()
<console>:10: error: could not find implicit value for parameter ordering: Ordering[A]
new collection.immutable.TreeMap[A, String]()
^
However if I explicitly specify the object A as the ordering it works fine.
scala> new collection.immutable.TreeMap[A, String]()(A)
res34: scala.collection.immutable.TreeMap[A,String] = Map()
Do I always have to explicitly specify the ordering or is there a shorter format?
Thanks
Mind you, there's a slightly less verbose way of creating an Ordering
:
implicit val OrderingA = Ordering.by((_: A).i)
The main advantage of Ordering being you can provide many of them for the same class. If your A
class is truly Ordered
, then you should just extend that. If not, instead of using implicits, you may pass an Ordering explicitly:
new collection.immutable.TreeMap[A, String]()(Ordering.by(_.i))
Notice the word "implicit" in the diagnostic. The parameter is declared implicit
meaning the compiler will try to find a suitable value in scope at the point you invoke the constructor. If you make your Ordering an implicit value, it will be eligible for this treatment by the compiler:
scala> implicit object A extends Ordering[A] { def compare(o1: A, o2: A) = o1.i - o2.i}
defined module A
scala> val tm1 = new collection.immutable.TreeMap[A, String]()
tm1: scala.collection.immutable.TreeMap[A,String] = Map()
Edit:
That example works in the REPL because the REPL encloses your code in invisible class definitions. Here's one that works free-standing:
case class A(val i:Int) extends Ordered[A] { def compare(o:A) = i - o.i }
object A { implicit object AOrdering extends Ordering[A] { def compare(o1: A, o2: A) = o1.i - o2.i } }
class B {
import A.AOrdering
val tm1 = new collection.immutable.TreeMap[A, String]()
}
Instead of extending Ordering[A]
, try extending Ordered[A]
. Like so:
scala> case class A(val i:Int) extends Ordered[A] {def compare(o:A) = i-o.i}
defined class A
scala> A(1)<A(2)
res0: Boolean = true
scala> A(1)<A(0)
res1: Boolean = false
scala> new collection.immutable.TreeMap[A, String]()
res3: scala.collection.immutable.TreeMap[A,String] = Map()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With