【问题标题】:Why does type inference in mutable and immutable sets behave so differently?为什么可变和不可变集合中的类型推断行为如此不同?
【发布时间】:2015-09-20 21:56:58
【问题描述】:

运行以下代码时,我得到了一些奇怪的结果:

object Example {

  implicit object StringOrdering extends Ordering[String] {
    def compare(o1: String, o2: String) = {
      o1.length - o2.length
    }
  }
  object StringOrdering1 extends Ordering[String] {
    def compare(o1: String, o2: String) = {
      o2.length - o1.length
    }
  }


  import collection.mutable
  import collection.immutable.TreeSet

  val x = TreeSet(1, 5, 8, 12)
  val y = mutable.Set.empty ++= x // mutable.Set[Int]
  val y1 = mutable.Set.empty[Int] ++= x // mutable.Set[Int]
  val z = TreeSet.empty ++ y // Set[Any]
  val z1 = TreeSet.empty[Int] ++ y // TreeSet[Int]
}

为什么可变集合和不可变集合中的类型推断行为如此不同? z 部分最令人费解,为什么我们至少没有得到一个TreeSet[Any]

【问题讨论】:

  • z 行不能在 2.10 或 2.11 上编译。
  • 必须有一些隐含的Ordering 在此处未显示的范围内,而不是Ordering[Int],甚至无法编译。

标签: scala type-inference


【解决方案1】:

问题可以简化成这样:

scala> TreeSet.empty[Int] ++ TreeSet.empty[BigInt]
res15: scala.collection.immutable.Set[Any] = Set()

您对TreeSet.empty 的使用并未透露它实际上是什么类型。事实上,它甚至不能按原样编译。我假设您在未显示的范围内有一些隐含的Ordering[A],其中A != Int

关于问题:

为什么我们至少没有得到一个 TreeSet[Any]

简单的答案是,如果没有Ordering[Any],就不能拥有TreeSet[Any]。如果我尝试将TreeSet[Int]TreeSet[BigInt] 组合在一起,它们最常见的类型是AnyTreeSetSortedSet 的一个类型,但是我们如何对一组 Any 进行排序呢?默认情况下,我们不能,因为对一组Any 进行排序实际上没有意义。

如果我真的想,我可以设计一个Ordering[Any],我最终会得到一个TreeSet[Any]

implicit val ordAny = new Ordering[Any] {
    def compare(x: Any, y: Any): Int = Ordering.Int.compare(x.hashCode, y.hashCode)
}

scala> TreeSet.empty[Int] ++ TreeSet.empty[BigInt]
res8: scala.collection.immutable.TreeSet[Any] = TreeSet()

但这并没有任何意义。

技术上的答案是,为了连接两个TreeSets、TreeSet[A]TreeSet[B],我们需要一个隐式CanBuildFrom[TreeSet[A], B, TreeSet[B]]

一些 CanBuildFroms 由SortedSetFactory 生成,但请注意它们如何需要隐式Ordering[A]。因为找不到Ordering[Any],所以编译器会寻找更通用的东西,然后找到Set[Any]。这是有道理的,因为如果我们将元素放入一个我们不知道如何排序的有序集合中,那么我们就不再有一个有序集合。剩下的只是一个普通的Set

【讨论】:

  • 确实,我已经将一些代码发送到控制台并稍后将其删除(我使用的是intellij)。问题已编辑。
猜你喜欢
  • 2011-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-19
  • 2011-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多