2009-04-25 7 views
5

Ich habe eine Klasse, die ich gerne in einer scala.collection.mutable.PriorityQueue verwenden möchte, aber ich möchte sie nicht nur für diesen einen Zweck geordnet machen [A]. Ich betrachte die Reihenfolge, die ich in Bezug auf die PriorityQueue verwenden möchte, nicht als natürliche Reihenfolge der Klasse.Scala: Gibt es eine Möglichkeit, PriorityQueue wie in Java zu verwenden?

Also, in meiner PriorityQueue möchte ich die Werte nach "Sequenz" geordnet werden. Nur weil zwei Objekte dieselbe Sequenz haben, sind sie natürlich nicht gleich, da der Inhalt ihrer "Werte" unterschiedlich sein kann.

Hier ist es in Java schön, der PriorityQueue ein alternatives Comparator-Objekt zur Verfügung stellen zu können. Mein Comparator würde die Objekte einfach in Bezug auf ihre "Sequenz" ordnen und ihre "Werte" ignorieren.

Die Klasse Priorityqueue muss mit einem parametriert werden „bestellte ein <% [A]“

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

Von dem, was ich gelesen habe, bedeutet dies, meine Klasse [A] oder ich muss eine bieten bestellt sein dürfen "Implizite Def" -Typ Umwandlung in Ordered [A], die sich ehrlich gesagt unelegant anfühlt.

Die Java-Lösung scheint "funktionaler" zu sein und erlaubt mir, ein Comparator-ähnliches Objekt zu übergeben, anstatt mich in eine Klassenhierarchie zu zwingen oder meine Klasse anzupassen.

Ich weiß, es gibt Alternativen zur Verwendung von PrioirityQueue, aber ich fühle mich, als würde ich hier gegen die Scala Lernkurve stoßen und möchte nicht aufgeben, ohne diese Designentscheidung voll zu erforschen.

Ist das nur eine unglückliche Entscheidung in der Scala-Bibliothek oder missverstehe ich eine Art von Aufrufkonvention, die PriorityQueue brauchbarer und 'funktional' macht?

Dank

Antwort

9

Die Syntax

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

ist wirklich nur ein Licht sugaring oben auf

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

Dies bedeutet, dass Sie Ihre eigene Methode A => bestellt [A]

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

Und übergeben Sie es manuell in Ihren PriorityQueue-Konstruktor

new PriorityQueue[Foo]()(orderedFoo) 
3

Die Konvertierungsfunktion von A bis Bestellte [A], um die Rolle von Java Komparator spielen kann. Die Funktion muss nur in dem Bereich sichtbar sein, in dem Sie PriorityQueue erstellen, sodass sie nicht zu einer "natürlichen Reihenfolge" für Ihr Objekt wird.

2

beide (korrekt) Antworten vor diesem in übersetzbar Code Kombination:

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

Sein Beispiel für Sie nicht nur kompilieren würde, weil (ich angenommen) Sie es an den Compiler werfen, wie sie ist. Sie können keine Top-Level-Methoden in scala kompilieren, alles muss in einem Objekt sein.

2

In Scala 2.8.0, ändert sich der Priorityqueue zu

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

Und die Bestellung [A] in Scala ist ähnlich Vergleicher in Java