String 理解Scala中的字符串和映射方法
我编写了以下简单示例来了解map方法的工作原理:String 理解Scala中的字符串和映射方法,string,scala,dictionary,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))
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)
};
}
我不太明白为什么bcd打印在
//2
。因为Scala将每个字符串都视为一个Seq
,所以我认为test.map(c=>(c+1.toChar)
应该生成另一个Seq
。正如//1
所建议的向量(b,c,d)
。但正如你所看到的,它没有。为什么?它实际上是如何工作的?当您使用map时,会发生以下情况:[List | Seq | etc].map([eachement]=>[do something])
map对左侧变量的每个元素应用一些操作:“abc”。map(字母=>字母+1)
将向字符串的每个元素添加1。字符串
abc
的每个元素在这里称为“字母”(类型为Char
)
“abc”是一个字符串,就像C++一样,它被当作一个字符数组。但是由于test
是String类型,map函数也会给出一个字符串
我尝试了以下方法:
val test2 : Seq[Char] = "abc"
但是我仍然得到一个String类型的结果,我猜Scala会自动地将Seq[Char]转换为String
我希望有帮助 这是Scala集合的一项功能(在本例中,字符串被视为字符集合)。真正的解释是相当复杂的,涉及到对类型类的理解(我想,这就是为什么在评论中提到Haskell),但简单的解释并不难
关键是,Scala集合库的作者非常努力地避免代码重复。例如,String
上的map
函数实际上是在这里定义的:scala.collection.TraversableLike#map
。另一方面,这种任务的简单方法会使map
返回TraversableLike
,而不是调用map
的原始类型(它是字符串
)。这就是为什么他们提出了一种方法来避免代码重复和不必要的类型转换或过于一般的返回类型
基本上,Scala collections方法(如map
)生成的类型与调用它时的类型尽可能接近。这是通过使用名为CanBuildFrom
的类型类实现的。地图的完整签名如下所示:
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
关于什么是typeclass有很多解释,CanBuildFrom
。我建议先看看这里。另一个很好的解释是:虽然它是用Haskell编写的,但这是我在Scala中学习FP的方式。我建议你购买和阅读。或者,我建议,这是在线免费的。@KevinMeredith你真的认为需要学习Haskell才能理解Scala字符串是如何工作的吗?出于这个原因,我只是发表评论,而不是回答。为了理解map
,我的观点和经验是,首先理解函数式编程的基础是值得的-因为map
是FP的基础。@KevinMeredith。。。特别是为了解释Scala的CanBuildFrom
,它在Haskell?@VictorMoroz中根本不存在——我发现的第25章(Scala集合的体系结构)很好地解释了CanBuildFrom
。还有-维克托,你打电话给我说的关于CanBuildFrom
的事也很有道理。我应该阅读这个问题,而不是假设它是关于理解FP中的map
。这个例子是,即使测试被声明为Seq[Char],它仍然被转换为字符串+1。真正简短的答案是Scala的收集操作像Smalltalk一样保留类型,而不是像Java一样保留最一般的类型,.NET(IEnumerable
)或Ruby(Array
)。