Scala:作为map()的参数

时间:2016-03-14 12:04:58

标签: scala

如何在以下示例中的map特征中使用Iterable方法?

据我所知,这个方法将返回一个我必须调用以执行内部逻辑的函数。

trait Container[E] {
    def += (e: E): Unit
}

trait Iterable[E, C[X] <: Container[X]] 
{
    def iterator(): Iterator[E]
    def build[F](): C[F]

    def map[F](f : (E) => F) : C[F] = {
        val res = build[F]()
        val iter = iterator()
        while (iter.hasNext) res += f(iter.next())
        res
    }

}

class Buffer[T] extends Container[T]
{
    val list = scala.collection.mutable.ListBuffer.empty[T]
    def Children = list
    def += (e: T): Unit = list += e
}   


class Range(val low: Int, val high: Int) extends Iterable[Int, Buffer] {

    def iterator() = new Iterator[Int] 
    {
        private var i = low
        def hasNext = i <= high
        def next() = { i += 1; i - 1 }
    }
    def build[F]() = new Buffer[F]
}

val range = new Range(1, 3)
var list = range.map[String](_)

2 个答案:

答案 0 :(得分:1)

new Range(2,5).map(_.toString)

答案 1 :(得分:1)

该方法具有以下特征:

trait Iterable[E, C[X] <: Container[X]] {
  def map[F](f : (E) => F) : C[F]
  // ...
}

首先,让我们看一下f参数的类型。签名(E) => F表示f是一个函数,它接受类型E的单个参数并返回类型F的值。具有此签名的任何函数(或方法)都可以作为参数传递给map()。另请参阅Scala documentation

要理解的另一个重要事项是map函数是通用的类型参数F。此类型参数的值可以手动指定,也可以由编译器从传递给map的参数中推断出来:

new Range(1,2).map[String](_.toString) // F is String
// new Range(1,2).map[Int](_.toString) // F is Int, compilation will fail

val mapFunction: Int => String = _.toString
new Range(1,2).map(mapFunction) //  mapFunction is a function from Int to String,
                                // the compiler infers F is String

基本上,例如使用Range,您可以向map()函数传递任何带有Int参数的函数(因为RangeE绑定到Int)并返回任何内容(Unit除外)。还有一些例子:

val r = Range(1,2)
val v1: Buffer[String] = r.map(_.toString)
val v2: Buffer[Int] = r.map(i => i + 1)
val v3: Buffer[Double] = r.map(Int.int2double)
val i: Int = 1
val v4: Buffer[Int] = r.map(i.max)

正如您所看到的,map()会返回Buffer[F]类型,因为Range绑定到C[X]类型参数。

正如@vitalii指出的那样,这个问题与高等级的类型无关。有关这些内容的详细信息,请查看other questionsblogs