2010-04-21 11 views
6

Estoy cambiando de scala 2.7 y pedido a scala 2.8 y utilizando pedidos. Parece bastante directo, pero me preguntaba si podría hacerlo un poco menos detallado. Por ejemplo:Scala 2.8 TreeMap y pedido personalizado

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 

si yo intento crear una TreeMap consigo un 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]() 
    ^

Sin embargo, si puedo especificar explícitamente el objeto A como el ordenar que trabaja muy bien.

scala> new collection.immutable.TreeMap[A, String]()(A) 
res34: scala.collection.immutable.TreeMap[A,String] = Map() 

¿Siempre tengo que especificar explícitamente el pedido o hay un formato más corto?

Gracias

+1

ADVERTENCIA: la comparación de las entradas restando NO FUNCIONA. También se aplica a la mayoría de las respuestas dadas aquí. http://stackoverflow.com/questions/2728793/java-integer-what-is-faster-comparison-or-subtraction –

+0

... * iff * las entradas son * grandes * y tienen signos opuestos. El número puede desbordarse produciendo el resultado opuesto ya que el signo cambia. Pero si está trabajando con números * que * están cerca de 'Int.MAX_VALUE', ya está jugando con fuego, ¿verdad? Creo que la resta de "idiom" es particularmente conciso/útil en scala ya que scala no tiene (ternary) expresiones condicionales (? :) – kornfridge

Respuesta

10

Aviso la palabra "implícita" en el diagnóstico. El parámetro está declarado implicit, lo que significa que el compilador intentará encontrar un valor adecuado en el alcance en el punto en que invoque al constructor. Si haces tu pedido un valor implícito, será elegible para este tratamiento por el compilador:

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() 

Editar:

Ese ejemplo trabaja en el REPL porque el REPL encierra su código en las definiciones de clase invisibles. Aquí hay una que funciona de independiente:

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]() 
} 
+0

Si intento eso en mi código me dicen "error: el modificador' implicit 'no puede ser usado para objetos de nivel superior ". Entonces, ¿hay alguna forma de hacer esto para los objetos de nivel superior? – Dave

+0

@Dave No existe, pero puede poner tal implícito dentro de un objeto de paquete para el paquete que contiene 'A'. –

+0

@ Daniel: ¿Lo intentó? Lo hice, pero de alguna manera fui rechazado por el compilador. No sé si lo hice mal o no está permitido. –

5

En lugar de extender Ordering[A], intente extender Ordered[A]. De este modo:

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() 
+1

La forma en que funciona es que una prioridad implícita baja convierte el pedido [A] al pedido [A] para TreeMap.Lamentablemente, serializamos TreeMaps para almacenamiento y la clase del pedido es un poco volátil (algunos $$ anon $ class). – Dave

13

Eso sí, hay una manera un poco menos detallado de crear un Ordering:

implicit val OrderingA = Ordering.by((_: A).i) 

La principal ventaja de ser pedidos que se puede brindar muchos de ellos de la misma clase. Si su clase A es verdaderamente Ordered, entonces simplemente debe extender eso. De lo contrario, en lugar de utilizar implícitos, puede pasar un pedido explícitamente:

new collection.immutable.TreeMap[A, String]()(Ordering.by(_.i)) 
+0

Parece conciso, comprensible y flexible. – javadba

+0

Vine aquí de nuevo, quería votar/comentar pero ... ¡ya he estado allí! – javadba

Cuestiones relacionadas