Predef.StringCanBuild

I came across an unexpected implementation of Predef.StringCanBuildFrom , which violates the assumptions I made on CanBuildFrom in my code. Here's the implementation:

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

It seems completely unnatural that apply(String) just ignores the parameter. For me, the correct implementation should be

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

but it seems so trivial that I cannot believe that I am one of those who have noticed this, since language exists. I was tempted to open the problem for this, but if I lacked any good reason not to do what I suggested, tell me!

+5
source share
1 answer

I think you underestimate the purpose of apply(from) .

The documentation says:

Creates a new constructor at the request of the collection.
@param from a collection requiring creator creation.
@return builder for collections of type To with element type Elem . Collection frames are usually organized so that the created builder builds the same kind of collection as from .

Thus, it was used to resolve the linker using the collection runtime type and, possibly, to copy some auxiliary data from the source collection. For example, the implementation in scala.collection.generic.GenTraversableFactory#GenericCanBuildFrom simply def apply(from: Coll) = from.genericBuilder[A] . As you can see, the actual data is not copied from the collection of arguments.

Actually, your implementation of CanBuildFrom will lead to incorrect results for standard implementations of map , flatMap and other general functions:

 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 
+3
source

Source: https://habr.com/ru/post/1263149/


All Articles