Predef.StringCanBuildFrom的行为

Dic*_*ici 5 scala

我偶然发现了Predef.StringCanBuildFrom令人惊讶的实现,这打破了我CanBuildFrom在代码中所做的假设.这是实施:

implicit def stringCanBuildFrom: CanBuildFrom[String, Char, String] = 
    new CanBuildFrom[String, Char, String] {
      def apply(from: String) = apply()
      def apply() = mutable.StringBuilder.newBuilder
}
Run Code Online (Sandbox Code Playgroud)

apply(String)简单地忽略参数似乎完全不自然.对我来说,正确的实施应该是

implicit def stringCanBuildFrom: CanBuildFrom[String, Char, String] = 
    new CanBuildFrom[String, Char, String] {
      def apply(from: String) = apply() ++= from
      def apply() = mutable.StringBuilder.newBuilder
}
Run Code Online (Sandbox Code Playgroud)

但这似乎是微不足道的,以至于我无法相信我是那个因为语言存在而发现它的人.我很想为此开一个问题,但是如果我错过任何没有理由不做我的建议,请告诉我!

Kol*_*mar 3

我认为你误解了目的apply(from)

它的文档说:

根据集合的请求创建一个新的构建器。来自请求创建构建器的集合的
@param 。
@returnTo具有元素 type 的 类型集合的构建器Elem。集合框架通常会进行安排,以便创建的构建器将构建与 相同类型的集合from

因此,它用于使用集合的运行时类型来解析构建器,并且可能从原始集合中复制一些辅助数据。例如,中的实现scala.collection.generic.GenTraversableFactory#GenericCanBuildFrom很简单def apply(from: Coll) = from.genericBuilder[A]。正如您所看到的,没有从参数集合中复制实际数据。

实际上,您的实现会为和其他通用函数CanBuildFrom的标准实现产生错误的结果:mapflatMap

import scala.collection.generic.CanBuildFrom
import scala.collection.mutable

implicit def stringCanBuildFrom: CanBuildFrom[String, Char, String] =
  new CanBuildFrom[String, Char, String] {
    def apply(from: String) = apply() ++= from
    def apply() = mutable.StringBuilder.newBuilder
  }

scala> "foo".map(identity)(stringCanBuildFrom)
res1: String = foofoo 
Run Code Online (Sandbox Code Playgroud)