加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

了解GenericTraversableTemplate和其他Scala收集内部

发布时间:2020-12-16 09:10:38 所属栏目:安全 来源:网络整理
导读:我和一个熟悉的Kotlin,Clojure和 Java8粉丝的朋友交换了电子邮件,问他为什么不Scala.他提供了很多原因(Scala太学术,功能太多,不是我第一次听到这个,我觉得这很主观) 但他最大的痛点就是一个例子,他不喜欢一个他不能理解基本数据结构实现的语言,他以LinkedLis
我和一个熟悉的Kotlin,Clojure和 Java8粉丝的朋友交换了电子邮件,问他为什么不Scala.他提供了很多原因(Scala太学术,功能太多,不是我第一次听到这个,我觉得这很主观)
但他最大的痛点就是一个例子,他不喜欢一个他不能理解基本数据结构实现的语言,他以LinkedList为例.

我看了一下scala.collection.LinkedList并计算了我理解或有些理解的东西.

> CanBuildFrom – 经过一番努力,我得到它,键入类,而不是最长的自杀笔记
在历史上[1]
> LinkedListLike – 我不记得我在哪里读了,但我相信这是有一个很好的理由

但是我开始盯着这些

> GenericTraversableTemplate – 现在我正在抓我的头
> SeqFactory,GenericCompanion – 好的,现在你失去了我,我开始明白他的观点

有理解这个的人可以在LinkedList的上下文中解释GenericTraversableTemplate SeqFactory和GenericCompanion吗?他们是什么,对他们的最终用户有什么影响(例如我确定他们在那里有一个很好的理由,这是什么原因?)

他们在那里有实际的理由吗?还是可以简化的抽象级别?

我喜欢Scala系列,因为我不必了解内部能够有效地使用它们.我不介意复杂的实现,如果它帮助我保持我的使用更简单.例如如果我有能力使用它来编写更干净的更优雅的代码,我不介意支付一个复杂的图书馆的价格.但是一定要更好地了解它.

[1] – Is the Scala 2.8 collections library a case of “the longest suicide note in history”?

解决方法

我将尝试从随机行人角度来描述这些概念(我从来没有为Scala收藏库贡献一条线,所以如果我错了就不要打我太难).

由于LinkedList现在已被弃用,因为Maps提供了一个更好的例子,我将使用TreeMap作为示例.

CanBuildFrom

动机是这样的:如果我们采取一个TreeMap [Int,Int]并将其映射

case (x,y) => (2 * x,y * y * 0.3d)

我们得到TreeMap [Int,Double].这种类型的安全本身就已经解释了必要性
简单的genericBuilder [X]构造.
但是,如果我们映射它

case (x,y) => x

我们获得一个Iterable [Int](更准确地说:一个List [Int]),这不再是一个Map,容器的类型已经改变了.这是CBF发挥作用的地方:

CanBuildFrom[This,X,That]

可以看作是一种“类型功能”,告诉我们:如果我们映射一个类型的集合
这个函数返回X类型的值,我们可以构建一个.最具体的
CBF在编译时提供,在第一种情况下,它将是类似的

CanBuildFrom[TreeMap[_,_],(X,Y),TreeMap[X,Y]]

在第二种情况下,Iterable[X]]

所以我们总是得到正确的容器类型.这个模式很普通.
每次你有一个通用功能

foo[X1,...,Xn](x1: X1,xn: Xn): Y

其中结果类型Y取决于X1,…,Xn,可以引入隐式参数
如下:

foo[X1,....,Y](x1: X1,xn: Xn)(implicit CanFooFrom[X1,Y]): Y

然后定义类型级别的函数X1,Xn→> Y分段提供多个
隐含的CanFooFrom的.

LinkedListLike

在类定义中,我们看到如下:

TreeMap[A,B] extends SortedMap[A,B] with SortedMapLike[A,B,TreeMap[A,B]]

这是Scala表达所谓的F边界多态性的方式.
动机如下:假设我们有十几个(或至少两个…)的特征SortedMap [A??,B]的实现.现在我们要实现一个没有Head的方法,可以看看
有点像这样:

def withoutHead = this.remove(this.head)

如果我们将实现移到SortedMap [A??,B]本身,那么我们可以做的最好的就是:

def withoutHead: SortedMap[A,B] = this.remove(this.head)

但这是我们可以得到的最具体的结果类型吗?不,太模糊了.
如果原始地图是TreeMap,我们希望返回TreeMap [A??,B]
CrazySortedLinkedHashMap(或任何…)如果原来是CrazySortedLinkedHashMap.
这就是为什么我们将实现移动到SortedMapLike中,并给予notHead方法以下签名:

trait SortedMapLike[A,Repr <: SortedMap[A,B]] {
  ...
  def withoutHead: Repr = this.remove(this.head)
}

现在因为TreeMap [A??,B]扩展了SortedMapLike [A,TreeMap [A??,B]],结果类型
withoutHead是TreeMap [A??,B]. CrazySortedLinkedHashMap也是一样:我们得到确切的类型.在Java中,您必须返回SortedMap [A??,B]或覆盖每个子类中的方法(这证明是Scala中功能丰富的特征的维护噩梦)

GenericTraversableTemplate

类型是:GenericTraversableTemplate [A,CC [X]&lt ;: GenTraversable [X]]

据我所知,这只是一个提供实现的特质
方法以某种方式返回具有相同容器类型的常规集合,但是
可能不同的内容类型(像平整,转置,解压缩的东西).

东西像foldLeft,减少,存在不在这里,因为这些方法只关心内容类型,而不是容器类型.

像flatMap这样的东西不在这里,因为容器类型可以改变(再次,CBF的).

为什么它是一个单独的特质,它有存在的根本原因吗?
我不这么认为,这可能会有些不一样的方法来分组方法.但这是自然而然的事情:你开始实现一个特质,结果证明它有很多方法.所以,你组合松散相关的方法,并把它们放在10个不同的特征与尴尬的名字,如“GenTraversableTemplate”,并将它们全部组合到你需要他们的特征/类

GenericCompanion

这只是一个实现一些常见的基本功能的抽象类
对于大多数集合类的伴侣对象(基本上,它只是实现非常
简单的工厂方法适用(varargs)和空).

例如,有一些方法适用于使用某些类型A的varargs并返回类型为CC [A]的集合:

Array(1,2,3,4) // calls Array.apply[A](elems: A*) on the companion object
List(1,4) // same for List

实现非常简单,就像这样:

def apply[A](varargs: A*): CC[A] = {
  val builder = newBuilder[A]
  for (arg <- varargs) builder += arg
  builder.result()
}

这对于数组和列表和TreeMaps以及几乎所有其他内容来说显然是一样的,除了像Bitset这样的“不规则集合”.所以这只是大多数伴侣对象的共同祖先类中的常用功能.没什么特别的.

SeqFactory

与GenericCompanion类似,但这次更具体针对Sequences.
添加一些常见的工厂方法,如fill()和iterate()和tabulate()等.
再次,这里没有什么特别的火箭科学

几句俗话

一般来说:我不认为应该尝试了解这个图书馆的每一个特征.相反,应该尝试整体看图书馆.作为一个整体,它有一个非常有趣的建筑.而在我个人看来,它实际上是一个非常美观的软件,但是一个人必须盯着它一段时间(并尝试重新实现整个架构模式几次)来掌握它.另一方面,例如CBF是一种“设计模式”,显然应该在这种语言的继承者中消除.整个故事与隐含的CBF的范围仍然对我来说总是噩梦.但是,许多事情起初似乎完全不可思议,而且几乎总是以一个顿悟(这是非常具体的Scala)结束:对于大多数其他语言,这种斗争通常以思想结束“这是一个完整的白痴的作者”) .

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读