2010-04-21 15 views
6

Przełączam się z wersji 2.7 i zamawiam na scala 2.8 i zamawiam. Wygląda to dość prosto, ale zastanawiałem się, czy mogę sprawić, że będzie trochę mniej gadatliwy. Na przykład:Scala 2.8 TreeMap i niestandardowe zamówienie

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 

Gdybym następnie spróbuj utworzyć TreeMap pojawia się błąd

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

Jednak jeśli jawnie określić Object jako zamawiania działa dobrze.

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

Czy zawsze muszę jednoznacznie określić zamówienie lub czy istnieje krótszy format?

Dzięki

+1

OSTRZEŻENIE: porównanie ints przez ich odjęcie NIE DZIAŁA. Dotyczy również większości odpowiedzi tutaj podanych. http://stackoverflow.com/questions/2728793/java-integer-what-is-faster-comparison-or-subtraction –

+0

... * iff * ints są * duże * i mają przeciwne znaki. Liczba może następnie przepełnić, dając odwrotny wynik, ponieważ znak się przełącza. Ale jeśli pracujesz z liczbami *, które * zbliżają się do 'Int.MAX_VALUE', to już grasz z ogniem, prawda? Myślę, że odejmowanie "idiomu" jest szczególnie zwięzłe/użyteczne w scala, ponieważ scala nie ma (trójskładnikowych) wyrażeń warunkowych (? :) – kornfridge

Odpowiedz

10

Wskazówka słowo "niejawny" w diagnostycznych. Parametr jest zadeklarowany jako implicit, co oznacza, że ​​kompilator spróbuje znaleźć odpowiednią wartość w zakresie w punkcie, w którym wywołuje się konstruktor. Jeśli twój zamawiania wartość niejawny, będzie kwalifikować się do tego zabiegu przez kompilator:

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:

To przykład działa w REPL ponieważ REPL zamyka swój kod w definicjach niewidzialnych klasowych. Oto jeden który działa wolnostojące:

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

Jeśli spróbuję tego w moim kodzie otrzymuję komunikat "błąd: niejawny" modyfikator nie może być użyty dla obiektów najwyższego poziomu ". Czy istnieje sposób na zrobienie tego dla obiektów najwyższego poziomu? – Dave

+0

@Dave Nie ma, ale można umieścić taki niejawny wewnątrz obiektu pakietu dla pakietu, który zawiera "A". –

+0

@Daniel: Próbowałeś? Zrobiłem, ale jakoś zostałem odrzucony przez kompilator. Nie wiem, czy zrobiłem to źle, czy to naprawdę nie jest dozwolone. –

5

Zamiast powiększenia Ordering[A], spróbuj rozszerzenie Ordered[A]. Tak:

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

Sposób, w jaki działa, polega na tym, że niski priorytet niejawnie konwertuje uporządkowaną [A] na kolejność [A] dla mapy drzewa.Niestety serializujemy TreeMaps do przechowywania, a klasa zamawiania jest trochę zmienna (niektóre $$ anon $ class). – Dave

13

Pamiętaj, jest to nieco mniej gadatliwy sposób tworzenia Ordering:

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

Główną zaletą zamawiania istota może dostarczyć wielu z nich do tej samej klasy. Jeśli twoja klasa A jest naprawdę Ordered, powinieneś po prostu ją rozszerzyć. Jeśli nie, zamiast używać implikacji, możesz jawnie przekazać Zlecenie:

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

Wydaje się zwięzły, zrozumiały i elastyczny. – javadba

+0

Przyszedłem tu znowu, chciałem nagrać/komentować, ale ... już tam byłem! – javadba

Powiązane problemy