了解Scala中的字符串和map方法

时间:2016-06-23 15:04:20

标签: string scala dictionary

我编写了以下简单示例来了解map方法的工作原理:

object Main{
  def main (args : Array[String]) = {
    val test = "abc"
    val t = Vector(97, 98, 99)
    println(test.map(c => (c + 1)))               //1 Vector(98, 99, 100)
    println(test.map(c => (c + 1).toChar))        //2 bcd
    println(t.map(i => (i + 1)))                  //3 Vector(98, 99, 100)
    println(t.map(i => (i + 1).toChar))           //4 Vector(b, c, d)
  };
}

我不太明白为什么在//2打印bcd。由于Scala将每个String视为Seq,我认为test.map(c => (c + 1).toChar)应该生成另一个Seq。由//1建议Vector(b, c, d)。但正如你所看到的,它没有。为什么?它是如何运作的?

2 个答案:

答案 0 :(得分:7)

这是Scala集合的一个功能(在这种情况下,String被视为字符集合)。真正的解释非常复杂,涉及对类型类的理解(我猜,这就是评论中提到Haskell的原因),但简单的解释是,并不是很难。

关键是,Scala集合库作者非常努力地避免代码重复。例如,map上的String函数实际上是在此处定义的:scala.collection.TraversableLike#map。另一方面,这种任务的天真方法会使map返回TraversableLike,而不是map被调用的原始类型(它是String)。这就是为什么他们想出了一种方法,可以避免代码重复和不必要的类型转换或太一般的返回类型。

基本上,像map这样的Scala集合方法产生的类型尽可能接近它所调用的类型。这是使用名为CanBuildFrom的类型类实现的。 map的完整签名如下:

def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That

有很多解释什么是类型类和CanBuildFrom。我建议先看一下:http://docs.scala-lang.org/overviews/core/architecture-of-scala-collections.html#factoring-out-common-operations。另一个很好的解释是:Scala 2.8 CanBuildFrom

答案 1 :(得分:0)

当您使用地图时,会发生以下情况:[List|Seq|etc].map([eachElement] => [do something])

map将一些操作应用于左侧变量的每个元素:"abc".map(letter => letter + 1)将为String" abc"的每个元素添加1。 String abc的每个元素都在这里调用"字母" (类型为Char

" ABC"是一个String,就像在C ++中一样,它被视为一个字符数组。但由于test的类型为String,因此map函数也会给出一个String。

我尝试了以下内容:

val test2 : Seq[Char] = "abc"

但我仍然得到String类型的结果,我猜Scala会自动从Seq [Char]转换为String

我希望它有所帮助!