2009-04-25 7 views
5

Ho una classe che vorrei usare in scala.collection.mutable.PriorityQueue, ma non voglio renderlo ordinato [A] solo per questo scopo. Non considero l'ordine che voglio usare rispetto a PriorityQueue come l'ordinamento naturale della classe.Scala: C'è un modo per utilizzare PriorityQueue come farei in Java?

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

Quindi, nel mio PriorityQueue, vorrei che i valori fossero ordinati per "sequenza". Tuttavia, solo perché due oggetti hanno la stessa sequenza non li rende naturalmente uguali poiché il contenuto dei loro "valori" potrebbe essere diverso.

Qui è dove, in Java, è bello essere in grado di fornire un oggetto Comparator alternativo a PriorityQueue. Il mio comparatore ordina semplicemente gli oggetti rispetto alla loro "sequenza" e ignora i loro "valori".

La classe CodaConPriorita deve essere parametrizzato con un "A <% ordinato [A]"

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

Da quello che ho letto, questo significa che la mia classe deve estendere ordinato [A] o devo fornire una Conversione di tipo "implicito" su Ordinato [A], che, onestamente, si sente inelegante.

La soluzione Java sembra più "funzionale", permettendomi di passare un oggetto simile a una funzione Comparator invece di costringermi a una gerarchia di classi o a cercare la mia classe.

Mi rendo conto che ci sono alternative all'utilizzo di PrioirityQueue, ma mi sembra che mi stia sbattendo contro la curva di apprendimento di Scala qui e non voglio rinunciare senza esplorare completamente questa decisione di progettazione.

Questa è solo una decisione sfortunata nella libreria Scala o sto fraintendendo una sorta di convenzione di chiamata che rende PriorityQueue più utilizzabile e "funzionale"?

Grazie

risposta

9

La sintassi

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

è in realtà solo uno zuccheraggio luce sulla parte superiore del

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

Ciò significa che è possibile scrivere il metodo proprio A => ordinato [A]

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

E trasferirlo manualmente nel costruttore PriorityQueue

new PriorityQueue[Foo]()(orderedFoo) 
3

la funzione di conversione di A a ordinato [A] può svolgere il ruolo di Java comparatore. La funzione deve essere visibile solo nel campo di applicazione in cui crei PriorityQueue, quindi non diventerà un "ordinamento naturale" per il tuo oggetto.

2

combinazione di entrambe le risposte corrette() prima di questo uno in codice compilabile:

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

Il suo esempio non sarebbe compilare per voi solo perché (sto supponendo) si scagliò contro il compilatore così com'è. Non è possibile compilare i metodi di livello superiore in scala, tutto deve essere in un oggetto.

2

In scala 2.8.0, il CodaConPriorita cambia a

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

e l'ordinamento [A] a Scala è simile al comparatore in Java

Problemi correlati