为什么在理解中这两种模式匹配之间的行为存在差异?

ebr*_*hez 4 scala

考虑一下Map[String, Any]:

val m1 = Map(("k1" -> "v1"), ("k2" -> 10))
Run Code Online (Sandbox Code Playgroud)

现在让我们写一个for:

scala> for ((a, b) <- m1) println(a + b)
k1v1
k210
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.

现在让我们指定第二个成员的类型:

scala> for ((a, b: String) <- m1) println(a + b)
k1v1

scala> for ((a, b: Integer) <- m1) println(a + b)
k210
Run Code Online (Sandbox Code Playgroud)

在这里,当我指定一个类型时,会发生过滤,这很好.

现在说我想使用数组[Any]代替:

val l1 = Array("a", 2)
Run Code Online (Sandbox Code Playgroud)

事情破裂了:

scala> for (v: String <- l1) println(v)
<console>:7: error: type mismatch;
 found   : (String) => Unit
 required: (Any) => ?
Run Code Online (Sandbox Code Playgroud)

我的双重问题是:

  • 为什么第二次匹配过滤器也没有呢?
  • 有没有办法在第二种情况下表达这种过滤而不使用脏isInstanceOf

Dan*_*ral 12

好吧,后一个例子不起作用,因为它没有规范.关于什么是合理的行为有一些讨论.就个人而言,我希望它能像你一样工作.问题在于:

val v: String = (10: Any) // is a compile error
(10: Any) match {
    case v: String =>
} // throws an exception
Run Code Online (Sandbox Code Playgroud)

如果您不相信,请加入俱乐部.:-)这是一个解决方法:

for (va @ (v: String) <- l1) println(v)
Run Code Online (Sandbox Code Playgroud)


Mar*_*sky 9

为了清楚起见,我们希望鼓励人们添加类型注释.如果在理解中,它们可能会成为非常昂贵的过滤操作,这是我们想要避免的陷阱.但是,我同意我们应该更容易指定某些东西是一种模式.可能一对parens就足够了.

val x: String = y       // type check, can fail at compile time
val (x: String) = y     // pattern match, can fail at run time

for (x: String <- ys)   // type check, can fail at compile time
for ((x: String) <- ys) // pattern match, can filter at run time
Run Code Online (Sandbox Code Playgroud)

  • 这种语法非常微妙.为什么不使用`case`来区分模式匹配形式? (2认同)