惯用语Scala:<collection> Like和<collection> Types?</collection> </collection>之间的语义差异

时间:2013-05-29 21:28:10

标签: scala naming scala-collections

正如这个问题的标题所暗示的那样:我的问题更多的是形式(惯用惯例)而不是功能。简洁地说:

  

MyCollectionLikeMyCollection之间的语义差异是什么?

例如:StringLikeStringMapLikeMap之间有什么区别。仔细查看Scala API文档,我可以看出XLike通常是X的超类型。但是,除此之外,我不清楚这些抽象层之间的语义差异。

在实践中,如果我正在创建一个新的类/特性,当我为所述类选择名称时,理解这种区别会很有帮助。

我遇到的具体问题如下:

  

我想创建特征:SurjectiveMap[K, T],可以与Map[K, Set[T]]MapLike[K, SetLike[T]]混合使用。鉴于我不知道*Like*之间的语义差异,我不确定该使用哪个。

2 个答案:

答案 0 :(得分:3)

与IFoo和Foo,Bar和BarImpl之间的区别相同(除了TraversableLike是包含实现的超级特征的事实):

  

Scala集合库避免了代码重复并实现了   通过使用通用构造函数和遍历来实现“相同结果类型”原则   在所谓的实现特征中的集合。这些特质是   以Like后缀命名;例如,IndexedSeqLike就是   IndexedSeq的实现特性,类似地,TraversableLike是   Traversable的实现特性。集合类如   Traversable或IndexedSeq继承了他们所有的具体方法   从这些特征中实现。

来自Scala collections architecture

答案 1 :(得分:1)

我认为使用Like特征可以优化返回(表示)类型。这涉及更多的工作。比较:

import collection.generic.CanBuildFrom

object FooMap {
  type Coll = FooMap[_, _]
  implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), FooMap[A, B]] = ???
}
trait FooMap[A, +B] extends Map[A, B] {
  def foo = 33
}

def test(f: FooMap[Any, Any]) {
  f.map(identity).foo  // nope, we ended up with a regular `Map`
}

object FooMap extends collection.generic.ImmutableMapFactory[FooMap] {
  override type Coll = FooMap[_, _]
  implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), FooMap[A, B]] = ???
  def empty[A, B]: FooMap[A, B] = ???
}
trait FooMap[A, +B] extends Map[A, B] 
  with collection.immutable.MapLike[A, B, FooMap[A, B]] {

  def foo = 33
  override def empty: FooMap[A, B] = FooMap.empty[A, B]
}

def test(f: FooMap[Any, Any]) {
  f.map(identity).foo  // yes
}

必须在MapLike特征之后混合Map特征才能启动正确的返回类型。


你似乎还没有免费获得所有东西,例如你需要覆盖更多的方法:

override def +[B1 >: B](kv: (A, B1)): FooMap[A, B1]  // etc.