2009-04-25 12 views
5

Tengo una clase que me gustaría usar en un scala.collection.mutable.PriorityQueue, pero no quiero que se ordene [A] solo para este propósito. No considero que el orden que deseo utilizar con respecto a PriorityQueue sea el orden natural de la clase.Scala: ¿Hay alguna manera de usar PriorityQueue como lo haría en Java?

class MyObject (sequence: Int, values: List[String]) ... 

Por lo tanto, en mi Prioridad, me gustaría que los valores se ordenen por 'secuencia'. Sin embargo, solo porque dos objetos tengan la misma secuencia no los hace naturalmente iguales ya que los contenidos de sus 'valores' pueden ser diferentes.

Aquí es donde, en Java, es agradable poder proporcionar un objeto Comparator alternativo a PriorityQueue. Mi Comparador simplemente ordena los objetos con respecto a su 'secuencia' e ignora sus 'valores'.

La clase PriorityQueue tiene que parametrizar con una "A <% ordenado [A]"

class PriorityQueue[A <% Ordered[A]] extends ... 

Por lo que he leído, esto significa que mi clase ha ordenado [A] o que debe proporcionar una conversión de tipo "implicit imp" a Ordenado [A], que, sinceramente, se siente poco elegante.

La solución Java parece más "funcional", lo que me permite pasar un objeto similar a la función Comparator en lugar de forzarme a una jerarquía de clases o monopatrominear mi clase.

Me doy cuenta de que hay alternativas al uso de PrioirityQueue, pero creo que puedo estar tropezando con la curva de aprendizaje de Scala aquí y no quiero rendirme sin explorar esta decisión de diseño por completo.

¿Es esta una decisión desafortunada en la biblioteca de Scala o estoy malentendiendo algún tipo de convención de llamadas que hace que PriorityQueue sea más útil y funcional?

Gracias

Respuesta

9

La sintaxis

class PriorityQueue[A <% Ordered[A]] ... 

es realmente sólo una adición de sacarosa en la luz en la parte superior de

class PriorityQueue[A]()(implicit convert: A => Ordered[A]) ... 

Esto significa que usted puede escribir su propio método A => ordenado [A]

case class Foo(n: Int) 
def orderedFoo(f: Foo): Ordered[Foo] = new Ordered[Foo] { 
    def compare(other: Foo) = f.n.compare(other.n) 
} 

Y páselo manualmente a tu constructor de PriorityQueue

new PriorityQueue[Foo]()(orderedFoo) 
3

la función de conversión de la A a la ordenada [A] puede desempeñar el papel del comparador de Java. La función debe ser visible solo en el ámbito en el que crea PriorityQueue, por lo que no se convertirá en un "orden natural" para su objeto.

2

Combinando ambas respuestas (correctas) antes de éste en código compilables:

object o { 
    case class Foo(n: Int) 
    implicit def orderedFoo(f: Foo): Ordered[Foo] = new Ordered[Foo] { 
    def compare(other: Foo) = f.n.compare(other.n) 
    } 

    val x = new scala.collection.mutable.PriorityQueue[Foo]() 
} 

Su ejemplo no sería compilar para que sólo porque (estoy suponiendo) que arrojó a que el compilador como está. No puede compilar métodos de nivel superior en Scala, todo tiene que estar en un objeto.

2

En scala 2.8.0, el PriorityQueue cambia a

class PriorityQueue[A](implicit ord : Ordering[A]) 

Y la Orden [A] en la Scala es similar al Comparador en Java

Cuestiones relacionadas