以下代码片段工作正常,然后在不同文件中的一些代码更改后,我开始获得由于隐式转换的递归调用而导致的堆栈溢出。这是不是发生在任何人身上,如果有的话,那是什么问题。
implicit def comparable2ordered[A <: Comparable[_]](x: A): Ordered[A] =
new Ordered[A] with Proxy {
val self = x
def compare(y: A): Int = {
self.compareTo(y)
}
}
答案 0 :(得分:4)
首先,我认为堆栈溢出的原因是使用[A <: Comparable[_]]
。 存在类型在实践中意味着您无法将A
与任何内容进行比较。这意味着编译器正在“选择”隐式转换以在self.compareTo
调用中重新调用(因此递归)。如果您使用编译器开关 -XprintTypes
那该怎么办?
考虑Ordering
和Ordered
之间的差异。您的类型应该有隐式排序。
implicit def comp2ord[A <: Comparable[A]] = new Ordering[A] {
def compare(x : A, y : A) = x compareTo y
}
然后将这种排序转换为Ordered
:
implicit def ordering2order[A : Ordering](x : A) = new Ordered[A] {
def compare(y : A) = implicitly[Ordering[A]].compare(x, y)
}
没有隐式排序的用法:
scala> val df = new java.text.SimpleDateFormat("yyyy-MM-dd")
df: java.text.SimpleDateFormat = java.text.SimpleDateFormat@f67a0200
scala> TreeSet(df.parse("2011-03-04"), df.parse("2010-05-06"))
<console>:13: error: could not find implicit value for parameter ord: Ordering[java.util.Date]
TreeSet(df.parse("2011-03-04"), df.parse("2010-05-06"))
^
现在有一个隐含的排序......
scala> implicit def comp2ord[A <: Comparable[A]] = new Ordering[A] {
| def compare(x : A, y : A) = x compareTo y
| }
comp2ord: [A <: java.lang.Comparable[A]]java.lang.Object with Ordering[A]
scala> TreeSet(df.parse("2011-03-04"), df.parse("2010-05-06"))
res1: scala.collection.immutable.TreeSet[java.util.Date] = TreeSet(Fri Mar 04 00:00:00 GMT 2011, Thu May 06 00:00:00 BST 2010)
当然,您还需要从Ordering
到Ordered
的隐式转换,以便通过<
,>=
来利用scala的比较{1}}等:
scala> implicit def ordering2order[A : Ordering](x : A) = new Ordered[A] {
| def compare(y : A) = implicitly[Ordering[A]].compare(x, y)
| }
ordering2order: [A](a: A)(implicit evidence$1: Ordering[A])java.lang.Object with Ordered[A]
scala> df.parse("2010-04-05") < df.parse("2009-01-01")
res2: Boolean = false
如果您的类型A
是实现原型 Comparable
的Java类,则必须提供显式转换:
implicit def comp2ord(x : DateTime) = new Ordered[DateTime] {
def compare(y : DateTime) = x compareTo y
}