有人可以解释为什么下面的代码会编译吗?
Option("foo") match {
case x: List[String] => println("A")
case _ => println("B")
}
这给了我一个关于类型擦除的(预期的)警告,但它仍然可以编译。我希望这会引发类型错误,就像我匹配 on"foo"
而不是Option("foo")
.
谢谢!
有人可以解释为什么下面的代码会编译吗?
Option("foo") match {
case x: List[String] => println("A")
case _ => println("B")
}
这给了我一个关于类型擦除的(预期的)警告,但它仍然可以编译。我希望这会引发类型错误,就像我匹配 on"foo"
而不是Option("foo")
.
谢谢!
代码被注释了,所以让我们花点时间来细细品味:
/** If we can absolutely rule out a match we can fail early.
* This is the case if the scrutinee has no unresolved type arguments
* and is a "final type", meaning final + invariant in all type parameters.
*/
例如,请注意 None 不是最终的。我知道,对吧?
如果你曾经尝试过 scalac -Ypatmat-debug,这里的评论可能会有所帮助:
https://github.com/scala/scala/pull/650
可达性几乎触手可及:
https://issues.scala-lang.org/browse/SI-6146
但我看不到任何关于有朝一日可能会受到警告的承诺。出于性能原因?也可以说,它为什么要对 instanceOf[Foo[_]] 发出警告?
目前,规范第 8.2 - 8.4 节说明了为什么与 Foo[a] 匹配是有趣的(因为 a 获得的边界)。我想我会再读一遍。喝了杯咖啡之后。
trait Foo[+A]
final class Fuzz[+A] extends Foo[A]
final object Fooz extends Foo[Nothing]
object Futz extends Foo[Nothing]
//error
Fooz match {
case x: List[_] => println("A")
case _ => println("B")
}
//no error
Futz match { ... }
我会假设编译器同时将Option
andList
视为Product
,这就是它编译的原因。正如您所说,有关类型擦除的警告是预期的。这是使用另一个产品的示例:
scala> Option("foo") match {
| case x: Tuple2[String,String] => println("TUPLE")
| case x: List[String] => println("LIST")
| case _ => println("OTHER")
| }
<console>:9: warning: non variable type-argument String in type pattern (String, String) is unchecked since it is eliminated by erasure
case x: Tuple2[String,String] => println("TUPLE")
^
<console>:10: warning: non variable type-argument String in type pattern List[String] is unchecked since it is eliminated by erasure
case x: List[String] => println("LIST")
^
更新 w/r/t 案例类(因为下面的评论):
scala> case class Foo(bar: Int)
defined class Foo
scala> val y: Product = Foo(123)
y: Product = Foo(123)
我注意到当你匹配的值的类被声明为 final 时会显示一个错误(我们知道那String
是 final)。我仍然不知道为什么没有它就没有错误。