(我每天晚上都在使用Scala,并且在2.8.0b1 RC4中看到相同的行为。我是Scala的新人。)
我有两个SortedMap
,我想组成它们的联合。这是我要使用的代码:
import scala.collection._
object ViewBoundExample {
class X
def combine[Y](a: SortedMap[X, Y], b: SortedMap[X, Y]): SortedMap[X, Y] = {
a ++ b
}
implicit def orderedX(x: X): Ordered[X] = new Ordered[X] { def compare(that: X) = 0 }
}
这里的想法是'implicit'语句,意味着
X
可以转换为Ordered[X]
,然后将SortedMap
组合成另一个SortedMap
而不是仅映射即可。当我编译时,我得到
sieversii:scala-2.8.0.Beta1-RC4 scott$ bin/scalac -versionScala compiler version
2.8.0.Beta1-RC4 -- Copyright 2002-2010, LAMP/EPFL
sieversii:scala-2.8.0.Beta1-RC4 scott$ bin/scalac ViewBoundExample.scala
ViewBoundExample.scala:8: error: type arguments [ViewBoundExample.X] do not
conform to method ordered's type parameter bounds [A <: scala.math.Ordered[A]]
a ++ b
^
one error found
如果该类型参数绑定(bind)为
[A <% scala.math.Ordered[A]]
而不是[A <: scala.math.Ordered[A]]
,似乎我的问题就解决了。不幸的是,我什至无法弄清楚“ordered”方法的用途!谁能帮我追踪一下?失败了,我打算怎么做才能产生两个
SortedMap
的并集?如果我删除了Combine的返回类型(或将其更改为Map
),那么一切正常---但是我不能依靠排序后的返回值! 最佳答案
当前,您正在使用的是scala.collection.SortedMap
特性,其++
方法是从MapLike
特性继承的。因此,您看到以下行为:
scala> import scala.collection.SortedMap
import scala.collection.SortedMap
scala> val a = SortedMap(1->2, 3->4)
a: scala.collection.SortedMap[Int,Int] = Map(1 -> 2, 3 -> 4)
scala> val b = SortedMap(2->3, 4->5)
b: scala.collection.SortedMap[Int,Int] = Map(2 -> 3, 4 -> 5)
scala> a ++ b
res0: scala.collection.Map[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)
scala> b ++ a
res1: scala.collection.Map[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)
++
返回结果的类型是Map[Int, Int]
,因为这是唯一有意义的++
对象的MapLike
方法返回的类型。看来++
保留了SortedMap
的sorted属性,我猜这是因为++
使用抽象方法来进行串联,并且这些抽象方法被定义为保持 map 的顺序。要合并两个排序的映射,建议您使用
scala.collection.immutable.SortedMap
。scala> import scala.collection.immutable.SortedMap
import scala.collection.immutable.SortedMap
scala> val a = SortedMap(1->2, 3->4)
a: scala.collection.immutable.SortedMap[Int,Int] = Map(1 -> 2, 3 -> 4)
scala> val b = SortedMap(2->3, 4->5)
b: scala.collection.immutable.SortedMap[Int,Int] = Map(2 -> 3, 4 -> 5)
scala> a ++ b
res2: scala.collection.immutable.SortedMap[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)
scala> b ++ a
res3: scala.collection.immutable.SortedMap[Int,Int] = Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)
此
SortedMap
特征的实现声明了一个++
方法,该方法返回SortedMap
。现在,对有关类型边界的问题有几个答案:
Ordered[T]
是一个特征,如果将其混合在一个类中,则指定可以使用<
,>
,=
,>=
,<=
比较该类。您只需要定义抽象方法compare(that: T)
,该方法将-1
返回this < that
,将1
返回this > that
,将0
返回this == that
。然后根据compare
的结果在特征中实现所有其他方法。 T <% U
表示绑定(bind)在Scala中的 View 。这意味着T
类型可以是U
的子类型,也可以通过范围内的隐式转换将其隐式转换为U
。如果您放置<%
而不是<:
,则该代码有效,因为X
不是Ordered[X]
的子类型,但可以使用Ordered[X]
隐式转换将其隐式转换为OrderedX
。 编辑:关于您的评论。如果您使用的是
scala.collection.immutable.SortedMap
,那么您仍在编程而不是实现的接口(interface),因为不可变的SortedMap
被定义为trait
。您可以将其视为scala.collection.SortedMap
的更特殊的特征,它提供了其他操作(例如++
返回SortedMap
)和不可变的属性。这符合Scala的理念-倾向于不可变-因此我认为使用不可变SortedMap
没有任何问题。在这种情况下,您可以保证结果一定会被排序,并且由于集合是不可变的,因此无法更改。虽然,我仍然感到奇怪的是,
scala.collection.SortedMap
没有提供++
方法,女巫返回了SortedMap
作为结果。我所做的所有有限测试似乎都表明,将两个scala.collection.SortedMap
串联在一起的结果确实会生成一个保留了sorted属性的映射。