2010-04-21 4 views
6

Я переключаюсь с scala 2.7 и заказываю scala 2.8 и используя заказ. Это выглядит совершенно прямо, но мне было интересно, могу ли я сделать это немного менее подробным. Например:Scala 2.8 TreeMap и пользовательский заказ

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 

Если я затем попытаться создать TreeMap я получаю ошибку

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

Однако, если я явно указать объект А, как приказывать его прекрасно работает.

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

Должен ли я всегда указывать заказ или есть более короткий формат?

Благодаря

+1

ПРЕДУПРЕЖДЕНИЕ: сравнение ints путем вычитания их НЕ РАБОТАЕТ. Также применяется к большинству ответов, приведенных здесь. http://stackoverflow.com/questions/2728793/java-integer-what-is-faster-comparison-or-subtraction –

+0

... * iff * ints * big * и имеют противоположные знаки. Затем число может переполняться, что дает противоположный результат, поскольку знак переключается. Но если вы работаете с цифрами *, которые * близки к 'Int.MAX_VALUE', вы уже играете с огнем, не так ли? Я думаю, что вычитающая «идиома» особенно красноречива/полезна в scala, поскольку scala не имеет (тройных) условных выражений (? :) – kornfridge

ответ

10

Обратите внимание на слово "неявное" в диагностическом. Параметр объявлен implicit, что означает, что компилятор попытается найти подходящее значение в области видимости в момент, когда вы вызываете конструктор. Если вы сделаете ваш заказ неявное значение, то оно будет иметь право на это лечение компилятором:

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:

Этот пример работает в REPL, так как REPL заключает свой код в определениях невидимых классов. Вот один, который работает свободно стоящей:

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

Если я попробую это в своем коде, мне будет сказано, что «ошибка: неявный» модификатор не может быть использован для объектов верхнего уровня ". Итак, есть ли способ сделать это для объектов верхнего уровня? – Dave

+0

@Dave Нет, но вы можете поместить такой неявный внутри объекта пакета для пакета, который содержит 'A'. –

+0

@ Даниэль: Вы попробовали? Я сделал, но каким-то образом отказался от компилятора. Я не знаю, сделал ли я это неправильно или это действительно не допустимо. –

5

Вместо расширения Ordering[A], попробуйте расширения Ordered[A]. Как так:

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

То, как работает, заключается в том, что невысокий приоритет неявно преобразует упорядоченный [A] в Ordering [A] для TreeMap.К сожалению, мы сериализуем TreeMaps для хранения, а класс заказов немного изменчив (некоторые $$ anon $ class). – Dave

13

заметь, есть несколько менее многословным способ создания Ordering:

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

Основное преимущество упорядоченности будучи вы можете предоставить многие из них для того же класса. Если ваш класс A действительно Ordered, вам следует просто расширить его. Если нет, вместо использования имплицитов вы можете явно передать запрос:

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

Кажется лаконичным, понятным и гибким. – javadba

+0

Пришел сюда снова, хотел поддержать или комментировать, но .. Я уже был там! – javadba

 Смежные вопросы

  • Нет связанных вопросов^_^