Общий метод для возврата первого из двух значений - PullRequest
7 голосов
/ 14 августа 2011

Мне нужен метод, чтобы вернуть первое из двух упорядоченных значений. Я пробовал:

def first[T <: Ordered[T]](a: T, b: T) = {
  a compare b match {
    case -1 | 0 => a
    case 1      => b
  }
}

но получите

scala> first(3,4)
<console>:9: error: inferred type arguments [Int] do not conform to method first's 
type parameter bounds [T <: Ordered[T]]
       first(3,4)
       ^

Я полагаю, это потому, что Int необходимо преобразовать в RichInt, то есть Ordered[Int], а не Ordered[RichInt]. Что дальше?

Ответы [ 3 ]

8 голосов
/ 14 августа 2011

Я думаю, что вы ищете вид границы

def first[T <% Ordered[T]](a: T, b: T) = {
  a compare b match {
  case -1 | 0 => a
  case 1      => b
  }
}

Тогда

scala> first(3, 2)
res3: Int = 2

За кулисами граница вида будет компилироваться в неявный параметр, который преобразует тип T в Ordered[T]. Ответ Даниэля Собрала имеет хорошее объяснение: Что такое контекст Scala и границы просмотра?

Редактировать . Представленный в Scala 2.8, Ordering может быть предпочтительным способом сравнения, но я не смог найти однозначного руководства. Я предполагаю, что Ordered обладает преимуществом совместимости с Comparable в Java, и, как отмечали другие, существуют неявные преобразования между Ordered и Ordering.

8 голосов
/ 14 августа 2011

Вы можете использовать тип класса Ordering и привязку к контексту:

def first[T : Ordering](a: T, b: T) = {
  implicitly[Ordering[T]].compare(a, b) match {
    case -1 | 0 => a
    case 1      => b
  }
}

Обновление

Этот код может быть дополнительно упрощен, если вы import scala.math.Ordered._. Сопутствующий объект Ordered имеет неявное преобразование orderingToOrdered, поэтому все, что имеет Ordering, будет также рассматриваться как Ordered:

import scala.math.Ordered._

def first[T : Ordering](a: T, b: T) = if (a <= b) a else b
1 голос
/ 14 августа 2011

Вы можете просто использовать неявные параметры и методы упорядочения, чтобы сделать его более понятным:

def first[T](a: T, b: T)( implicit ord: Ordering[T] ) = {
  import ord._
  if( a <= b ) a else b
}

или, если вам все равно, какой из них возвращается в случае равенства:

def first[T](a: T, b: T)( implicit ord: Ordering[T] ) = 
  ord.min(a,b)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...