【问题标题】:Scala Map foreachScala Map foreach
【发布时间】:2012-01-26 12:02:45
【问题描述】:

给定:

val m = Map[String, Int]("a" -> 1, "b" -> 2, "c" -> 3)
m.foreach((key: String, value: Int) => println(">>> key=" + key + ", value=" + value))

为什么编译器会抱怨

error: type mismatch
found   : (String, Int) => Unit
required: (String, Int) => ?

【问题讨论】:

    标签: scala scala-collections


    【解决方案1】:

    我不确定错误,但您可以按如下方式实现您想要的:

    m.foreach(p => println(">>> key=" + p._1 + ", value=" + p._2))
    

    也就是说,foreach 接受一个接受一对并返回 Unit 的函数,而不是接受两个参数的函数:这​​里,p 的类型为 (String, Int)

    另一种写法是:

    m.foreach { case (key, value) => println(">>> key=" + key + ", value=" + value) }
    

    在这种情况下,{ case ... } 块是一个偏函数。

    【讨论】:

    • 很好,更符合动态语言 obj.each {k,v => ...} 的方法,比元组 ._1, ._2 语法更易读
    • 好奇,第二次使用(案例)是否有任何性能考虑?对于每个元素,尝试将它们分配给变量等。我希望我的代码可读,但也尽可能快。
    【解决方案2】:

    哎呀,读错了 doco,map.foreach 需要一个带有元组参数的函数字面量!

    所以

    m.foreach((e: (String, Int)) => println(e._1 + "=" + e._2))
    

    作品

    【讨论】:

    • 鉴于所涉及的类型是推断出来的,您可以简单地执行以下操作: m.foreach(e => println(e._1 + "=" + e._2)
    • 是否可以显示完整类型?地图很多,我关心的是哪一个。
    【解决方案3】:

    您需要对Tuple2 参数进行模式匹配,以将变量分配给其子部分keyvalue。您只需进行很少的更改即可:

    m.foreach{ case (key: String, value: Int) => println(">>> key=" + key + ", value=" + value)} 
    

    【讨论】:

    • 顺便说一句,您可以从键和值中删除类型注释。
    【解决方案4】:

    令人困惑的错误信息是编译器错误,应该是fixed in 2.9.2:

    【讨论】:

    • 我刚刚检查过(通过针对 2.9.1 和 2.9.2 编译 github.com/paulbutcher/baderrormessage)。我可以在 2.9.1 而不是 2.9.2 中看到问题。如果您有问题仍然存在的示例,也许您应该重新打开该错误?
    • 我刚刚使用 Scala 2.9.2(Java HotSpot 1.7.0 VM for Windows 64-bit ) 并且可以看到他的帖子中显示的同样荒谬的消息。
    • 以下是我从 Git 编译您的代码时发生的情况:欢迎使用 Scala 版本 2.9.2(Java HotSpot(TM) 64 位服务器 VM,Java 1.7.0)。输入表达式以对其进行评估。键入 :help 以获取更多信息。 scala> class Foo 扩展 Function2[Int, Int, Int] { | def apply(x: Int, y: Int) = x + y |覆盖 def tupled: (Int, Int) => Int = super.tupled | } :9: 错误:类型不匹配;找到 : ((Int, Int)) => Int required: (Int, Int) => Int override def tupled: (Int, Int) => Int = super.tupled ^
    • 那个错误信息是正确的。请注意,“找到”行中有两组括号。错误在于它过去只打印一组括号。如果您在 2.9.1 中尝试并比较输出,您会发现它们是不同的。
    【解决方案5】:

    很好的问题! 即使显式键入 foreach 方法,它仍然会给出非常不清楚的编译错误。有一些解决方法,但我不明白为什么这个例子不起作用。

    scala> m.foreach[Unit] {(key: String, value: Int) => println(">>> key=" + key + ", value=" + value)}
    <console>:16: error: type mismatch;
     found   : (String, Int) => Unit
     required: (String, Int) => Unit
                  m.foreach[Unit] {(key: String, value: Int) => println(">>> key=" + key + ", value=" + value)}
                                                             ^
    

    【讨论】:

      【解决方案6】:

      文档说参数是元组 -> 单元,所以我们可以很容易地做到这一点

      Map(1 -> 1, 2 -> 2).foreach(tuple => println(tuple._1 +" " + tuple._2)))
      

      【讨论】:

        【解决方案7】:

        另一种方式:

        Map(1 -> 1, 2 -> 2).foreach(((x: Int, y: Int) => ???).tupled)
        

        但是它需要显式类型注释,所以我更喜欢偏函数。

        【讨论】:

          猜你喜欢
          • 2010-12-17
          • 2017-10-17
          • 2018-04-10
          • 1970-01-01
          • 2014-11-03
          • 2013-06-09
          • 1970-01-01
          • 1970-01-01
          • 2021-11-25
          相关资源
          最近更新 更多