Skip to content

25장 The Architecture of Scala Collections

Changwoo Park edited this page Aug 14, 2014 · 2 revisions

25. The Architecture of Scala Collections

Scala Collection은 코드 중복을 최소화했다.

25.1 Builders

Colleciton Operation은 foreach가 있는 Traversable과 Collection을 만드는 Buidler로 구현된다.

Traversable은 24장에서 다뤘고, Builders가 뭔지는 아래 두 예제를 보면 알 수 있다:

package scala.collection.generic

class Builder[-Elem, +To] {
  def +=(elem: Elem): this.type
  def result(): To
  def clear()
  def mapResult(f: To => NewTo): Builder[Elem, NewTo] = ...
}
package scala.collection

class TraversableLike[+Elem, +Repr] {
  def newBuilder: Builder[Elem, Repr] // deferred
  def foreach[U](f: Elem => U) // deferred
  ...
  def filter(p: Elem => Boolean): Repr = {
    val b = newBuilder
    foreach { elem => if (p(elem)) b += elem }
    b.result
  }
}

25.2 Factoring out common operations

"same-result-type" 원칙을 지키고 코드 중복을 회피하는데 사용하려고 implementation trait이라는 걸 사용한다. Like suffix가 달린 Trait이 Implementation Trait이다. TraversableLikeTraversable의 Implemtation Trait이다. 즉 Traversable Collection의 Operation은 TraversableLike에 구현하고 상속 받는다.

아래는 TraversableTraversableLike의 선언부이다:

trait TraversableLike[+Elem, +Repr] { ... }
trait Traversable[+A] extends TraversableLike[A, Traversable[A]] with GenTraversable[A] with TraversableOnce[A] with GenericTraversableTemplate[A, Traversable] { ...}

TraversableLike는 여러 Traversable Collection에서 재사용할 수 있도록 엘리먼트 타입(A)뿐만 아니라 Colection 타입(Traversable[A])도 파라미터로 받는다.

책에서 보여주는 예제를 보면 BigSet[Int]의 map 함수는 BigSet[Float]를 반환한다:

scala> val bits = BitSet(1, 2, 3)
bits: scala.collection.immutable.BitSet = BitSet(1, 2, 3)

scala> bits map (_.toFloat)
res14: scala.collection.immutable.Set[Float]
= Set(1.0, 2.0, 3.0)

즉, 타입 파라미터가 3개인 Builder가 필요한데 TraversableLike의 Builder는 타입 파라미터가 두 개다:

def newBuilder: Builder[Elem, Repr]

그래서 Scala는 타입 파라미터가 2개인 Builder를 생성하는 타입 파라미터 3개인 CanBuildFrom을 implicit 파라미터로 넘겨 받는다:

def map[B, That](p: Elem => B)
    (implicit bf: CanBuildFrom[B, That, This]): That = {
  val b = bf(this)
  for (x <- this) b += f(x)
  b.result
}

CanBuildFrom의 생김새:

package scala.collection.generic

trait CanBuildFrom[-From, -Elem, +To] {
  // Creates a new builder
  def apply(from: From): Builder[Elem, To]
}

CanBuildFrom의 쓰임새:

CanBuildFrom[Set[_], A, Set[A]]

25.3 Integrating new collections

지금까지 설명한 것으로 Collection을 하나 만들어 본다.

Clone this wiki locally