简体   繁体   中英

Scala Collection CanBuildFrom

In Scala 2.10.2, I'm trying to learn more about the collections hierarchy by rolling some simple collections of my own.

Below is the source code for a toy class representing a sequence of integers.

import scala.collection.SeqLike
import scala.collection.mutable.Builder
import scala.collection.generic.CanBuildFrom

object IntSeq
{
    def apply( ints : Int* ) : IntSeq = new IntSeq( ints )

    protected def newBuilder( iterable : Iterable[Int] ) : Builder[Int,IntSeq] = new Builder[Int,IntSeq]
    {
        var init = scala.collection.mutable.ArrayBuffer( iterable.toSeq:_* )
        def +=( elem : Int ) : this.type = { init += elem; this } 
        def result() : IntSeq = new IntSeq( init ) 
        def clear() : Unit = init = scala.collection.mutable.ArrayBuffer[Int]()
    }

    implicit def canBuildFrom : CanBuildFrom[Iterable[Int],Int,IntSeq] = new CanBuildFrom[Iterable[Int],Int,IntSeq]
    {
        def apply() : Builder[Int,IntSeq]= newBuilder( Seq() )
        def apply( from : Iterable[Int] ) : Builder[Int,IntSeq] = newBuilder( from )
    }
}

class IntSeq( seq : Seq[Int] )
    extends Seq[Int]
    with SeqLike[Int,Seq[Int]]
{
    def sumSquared() = seq.map( i => i * i ).sum

    // SeqLike interface
    def iterator : Iterator[Int] = seq.iterator

    def apply( idx : Int ) : Int = seq( idx )

    def length : Int = seq.length
}

The problem I have is the following: in the summary section of the page "The Architecture of Scala Collections" , point 4 says that by providing an implicit canBuildFrom in the companion object, map and similar functions will return instances of this class. However, this does not happen:

scala> IntSeq( ( 1 to 10 ):_* ).filter( _ % 2 == 0 )
res0: Seq[Int] = List(2, 4, 6, 8, 10)

Can anyone shed some light on why this is?

Take a look what filter method returns. It returns type Repr from TraversableLike. That is the same type as second type parameter in SeqLike. In your case it's Seq[Int]. Everything works as expected. If you want to get type as IntSeq:

class IntSeq( seq : Seq[Int] )
    extends Seq[Int]
    with SeqLike[Int,IntSeq]

filter on a SeqLike[A, Repr] , like many similar methods, returns a value of type Repr . However, you made your class extend SeqLike[Int, Seq[Int]] . If you want operations on your class to return values of type IntSeq , you should extend SeqLike[Int, IntSeq] .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM