【问题标题】:Confusing type mismatch in ScalaScala中令人困惑的类型不匹配
【发布时间】:2014-06-04 11:48:08
【问题描述】:

我有:

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.countjava.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)) }
  }
}

第一行编译得很好,测试通过了。如果我将第一行替换为已注释掉的第二行,则会出现编译错误。

  • sbt 报告:found : (String, Int) => Unit, required: ((String, Int)) => Unit
  • IntelliJ IDEA 报告:Type mismatch, expected: ((String, Int)) => Unit, actual: (String, Int) => Unit

这是为什么?我该如何解决?

【问题讨论】:

  • How to iterate scala map? 的可能重复项
  • 在将映射值匹配到元组时,您似乎缺少case。试试forAll (map) { case (k: String, v: Int) => assert(v === expected(k)) }。有什么理由不只是检查 assert(map == expected) 的地图是否相等?
  • 因为一旦我走上这条路,我想了解为什么(k: String, v: Int) => assert(v === expected(k)) 是不可接受的。 :-)

标签: scala scalatest


【解决方案1】:

您正在使用的方法接受将 single 参数转换为单个输出的函数。您在第二个语句中告诉 Scala 的是 map 应该接受一个带有两个参数的函数!恰好是大小为 2 的元组的 单个 参数和两个不同的参数之间有一个重要区别。

所以你只有一个参数,但你(和 Scala)知道它是一个元组。要访问这两个元素,您必须 destructurepattern match 您的论点反对您想要的元组。您只需编写forAll (map) { case (k: String, v: Int) => assert(v === expected(k)) } 即可。您是说您收到的参数应该与元组(String, Int) 的模式匹配,并且您希望第一个元素绑定到k,第二个元素绑定到v。您可能可以消除在此处明确提及类型。请注意,这类似于模式匹配中使用的语法,本质上就是您在此处所做的。

【讨论】:

  • 究竟是什么case (k: String, v: Int) 使其确实 满足forAll (map) 的预期要求?
  • 这意味着“我在这里得到的单个参数应该看起来像(k:String,v:Int)”。所以你只接受一个参数,这是函数需要的。
【解决方案2】:

在第二个示例中,您定义了一个双参数函数,而不是单个元组参数函数。因此,为什么错误说它期望参数周围有双括号。

【讨论】:

  • 是的,但是为什么将它包裹在第二组括号中并不能解决问题?
  • 我认为会的。一个有趣的问题 :) 那么可以使用 { case (k,v) => ... }
  • @user3706801 我肯定会使用模式匹配语句。在我看到这条评论之前,我只是回答了这个问题。
猜你喜欢
  • 1970-01-01
  • 2012-09-12
  • 2017-03-11
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多