Create a custom scala collection where map defaults to returning the custom collection?

一世执手 提交于 2019-12-06 01:59:43

问题


The trait TraversableLike[+A, +Repr] allows one to make a collection where some functions will return a Repr, while others continue to return the type parameter That on the function. Is there a way to define a CustomCollection[A] where functions like map, ++, and others will default That as Repr if not inferred otherwise?

Here is a code snippet that hopefully describes what I would like:

case class CustomCollection[A](list: List[A]) extends TraversableLike[A, CustomCollection[A]] {
  protected[this] def newBuilder = new CustomCollectionBuilder[A]
  def foreach[U](f: (A) => U) {list foreach f}
  def seq = list
}

class CustomCollectionBuilder[A] extends mutable.Builder[A, CustomCollection[A]] {
  private val list = new mutable.ListBuffer[A]()
  def += (elem: A): this.type = {
    list += elem
    this
  }
  def clear() {list.clear()}
  def result(): CustomCollection[A] = CustomCollection(list.result())
}

object CustomCollection extends App {
  val customCollection = CustomCollection(List(1, 2, 3))
  println(customCollection filter {x => x == 1}) // CustomCollection(1)
  println(customCollection map {x => x + 1}) // non-empty iterator
}

I would like the last line to be CustomCollection(2, 3, 4).


回答1:


You need to set up a companion object which provides the refined CanBuildFrom instance:

import collection.TraversableLike
import collection.generic.{CanBuildFrom, GenericCompanion, GenericTraversableTemplate,
  TraversableFactory}
import collection.mutable.{Builder, ListBuffer}

object CustomCollection extends TraversableFactory[CustomCollection] {
  def newBuilder[A] = new CustomCollectionBuilder[A]
  implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, CustomCollection[A]] = 
    new CanBuildFrom[Coll, A, CustomCollection[A]] {
       def apply(): Builder[A, CustomCollection[A]] = new CustomCollectionBuilder()
       def apply(from: Coll): Builder[A, CustomCollection[A]] = apply()
    }
}
case class CustomCollection[A](list: List[A]) extends Traversable[A]
with TraversableLike[A, CustomCollection[A]]
with GenericTraversableTemplate[A, CustomCollection] {
  override def companion: GenericCompanion[CustomCollection] = CustomCollection
  def foreach[U](f: A => U) { list foreach f }
  override def seq = list
}

class CustomCollectionBuilder[A] extends Builder[A, CustomCollection[A]] {
  private val list = new ListBuffer[A]()
  def += (elem: A): this.type = {
    list += elem
    this
  }
  def clear() {list.clear()}
  def result(): CustomCollection[A] = CustomCollection(list.result())
}

val customCollection = CustomCollection(List(1, 2, 3))
val f = customCollection filter {x => x == 1} // CustomCollection[Int]
val m = customCollection map {x => x + 1}     // CustomCollection[Int]


来源:https://stackoverflow.com/questions/14299454/create-a-custom-scala-collection-where-map-defaults-to-returning-the-custom-coll

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!