来自scala参考: http://www.scala-lang.org/files/archive/nightly/docs/library/index.html#scala.math.Ordering
case class Person(name:String, age:Int)
val people = Array(Person("bob", 30), Person("ann", 32), Person("carl", 19))
// sort by age
object AgeOrdering extends Ordering[Person] {
def compare(a:Person, b:Person) = a.age compare b.age
}
但是如果我想使用Ordering对象对Seq进行排序:
// Want to sort a Seq, or event and IndexedSeq
val ps = people.asInstanceOf[collection.Seq[Person]]
// Type not enough arguments
// for method stableSort: (implicit evidence$6: scala.reflect.ClassTag[Person],
// implicit evidence$7: scala.math.Ordering[Person])Array[Person]. Unspecified value
// parameter evidence$7.
Sorting.stableSort(ps)(AgeOrdering)
编译器扼流圈。但是,stableSort API表示需要Seq。那么为什么上述失败呢?
答案 0 :(得分:2)
在Sorting中,quickSort
实现是就地完成的,有一堆基于索引的移动,只适合在数组上完成(和Seq一样根本没有定义索引。)
quickSort[K](a: Array[K] ..): Unit
quickSort方法对输入执行副作用并返回Unit。
然而,stableSort
有两个不同的表单。采用Seq和采用数组的采样器。
stableSort[K](a: Seq[K] ..): Array[K]
stableSort[K](a: Array[K] ..): Unit
采用数组的表单也返回Unit并修改输入(作为quickSort但确保稳定性),而表单采用Seq返回一个新的Array对象(并且输入序列未被修改)。
错误是因为quickSort
方法具有第二个参数组的签名:(implicit arg0: math.Ordering[K])
而stableSort
方法具有:(implicit arg0: ClassTag[K], arg1: math.Ordering[K])
- 也就是说, 还需要ClassTag [K / Person]。
即使指定了顺序,也没有指定(或隐式解析)ClassTag[K]
参数,Scala需要这个来创建内部使用的Array[Person]
(并返回)。由于Scala受到Java类型擦除的限制,该方法无法在没有其他帮助的情况下了解 类型K实际上是什么。
我不确定为什么它没有被隐含地解决(因为Scala暗示对我来说仍然是“神奇的”!),但明确传递相当容易:
val results = Sorting.stableSort(ps)(classTag[Person], AgeOrdering)
TypeTags and Manifests中讨论了TypeTag / ClassTag的一些理性和用法。