我有:
val words = List("all", "the", "words", "all", "the", "counts", "all", "day")
val map = Exercise02.count(words.iterator)
val expected = Map("all" -> 3, "the" -> 2, "words" -> 1, "counts" -> 1, "day" -> 1)
其中Exercise02.count
为java.util.Iterator[String] => Map[String, Int]
,仅生成输入java.util.Iterator[String]
中每个单词的计数。
我写了一个测试:
object Exercise02Spec extends FlatSpec with Inspectors {
val words = List("all", "the", "words", "all", "the", "counts", "all", "day")
val map = Exercise02.count(words.iterator)
val expected = Map("all" -> 3, "the" -> 2, "words" -> 1, "counts" -> 1, "day" -> 1)
"count" should "count the occurrence of each word" in {
forAll (map) { kv => assert(kv._2 === expected(kv._1)) }
// forAll (map) { (k: String, v: Int) => assert(v === expected(k)) }
}
}
第一行编译得很好,测试通过。如果我用注释掉的第二行替换第一行,我会收到编译错误。
found : (String, Int) => Unit, required: ((String, Int)) => Unit
Type mismatch, expected: ((String, Int)) => Unit, actual: (String, Int) => Unit
这是为什么?我该如何解决?
答案 0 :(得分:3)
您正在使用的方法接受将单个参数转换为单个输出的函数。你在第二个语句中告诉Scala的是,map应该接受一个带有两个参数的函数! 单个参数恰好是一个大小为2的元组和两个不同的参数之间存在重要区别。
所以你有一个论点,但你(和Scala)知道它是一个元组。要访问这两个元素,您必须 destructure 或模式匹配您对自己想要的元组的参数。您只需编写forAll (map) { case (k: String, v: Int) => assert(v === expected(k)) }
即可。您说您收到的参数应该与元组(String, Int)
的模式匹配,并且您希望第一个元素绑定到k
而第二个元素绑定到v
。您可以在此处明确省略提及类型。请注意,这与模式匹配中使用的语法类似,这基本上就是您在此处所做的。
答案 1 :(得分:0)
在第二个例子中,你定义了一个两个参数函数,而不是一个元组参数函数。因此,为什么错误说它期望围绕论证的双括号。