这是从Coursera在Scala课程中的函数式编程的第6周开始的。
我试图围绕下面的代码片段。如果charcode的参数列表中没有charCode
,如何将map
传递给字符串的(c: Char)
方法呢?
/* define the map of numbers to letters */
val nmem = Map( '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", '6'
-> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ")
/* invert the map the get a map of letters to digits */
val charCode: Map[Char, Char] = for ((digit, str) <- nmem; ltr <- str) yield
ltr -> digit
/* define a function that returns the numbers of a given word */
def wordCode(word: String): String = word.toUpperCase map charCode
我习惯将函数传递给map
,如下所示:
val s = "JAVA"
val str = s map (lower)
def lower(c: Char) = c.toLower
您可以看到lower
将char作为参数
此外,Odersky教授提到“类Map [Key,Value]也扩展了Function类型Key =&gt;值,因此可以在任何地方使用地图”。这就是为什么上面的代码有效吗?如果有,怎么样?我似乎无法找到任何关于此的文件? “地图可以在任何地方都可以使用”是什么意思?
非常感谢,
答案 0 :(得分:2)
你是对的。它有效,因为Map[A, B]
实现了 Function1[A, B]
。字符串的map
方法需要一个函数将每个字符转换为另一个字符。也就是Function1[Char, Char]
,可以写成Char => Char
。
当您使用map
致电Map[Char, Char]
时,编译器会检查它实际上是Char => Char
,因为它实现了Function1[Char, Char]
。
您可以将Map[A, B]
视为PartialFunction[A, B]
。也就是说,为有限数量的输入实现的功能。 Map[A, B]
只是从A
类型的键到类型B
的值的映射。因此,您的A => B
函数实现为:如果map包含A
类型的键,则返回其类型B
的值。如果它不存在,则不为该A
定义部分函数。
使其成为可能的层次结构是:
Map
实施MapLike
MapLike
实施PartialFunction
PartialFunction
实施Function1
然后,如果您查看MapLike
,就会找到def isDefinedAt(key: K) = contains(key)
。这告诉部分函数是否定义了给定值。然后,它还实现了def apply(key: K): V
所需的Function1
。
答案 1 :(得分:2)
您可以将地图视为部分函数的特殊类型 - 部分均值,不一定是所有值都已定义。
也就是说,地图m = Map[S,T]
也是S=>T
类型的函数。
让我们举个例子
scala> val includes = Map( 1 -> true, 2->false, 3-> false, 4->true)
includes: scala.collection.immutable.Map[Int,Boolean] = Map(1 -> true, 2 -> false, 3 -> false, 4 -> true)
scala> (1 to 4).filter(includes)
res6: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 4)
(如果缺少序列中的值,则会出现运行时错误。)
那么,在你的问题中,你是将Map charCode
传递给map函数,你会问为什么它会编译?
Scala中的String
是Java string
的类型别名。但在Predef
中,存在从String
到StringWrapper
的隐式转换(低优先级) - 将字符串转换为Char
和StringOps
的序列(注入集合方法的更高优先级(如map
)。您可以在strings的文档中阅读更多内容。
因此,Scala编译器将您的String视为Char
的序列,map函数使用提供的“函数”(即charCode
映射)转换每个成员。
答案 2 :(得分:1)
Map[A, B]
延伸PartialFunction[A, B]
。尽管这有点red-herring,但每个PartialFunction[A, B]
也是一个函数A => B
(如果无法找到密钥,它会抛出错误)。 map
方法需要一个函数A => B
,所以一切都很合适。
总结一下,
charCode
是Map[Char, Char]
PartialFunction[Char, Char]
Char => Char
string.map