在此示例中:
scala> val a: Seq[Int] = Array(1,2,3)
a: Seq[Int] = WrappedArray(1, 2, 3)
发生隐式转换,Array
转换为扩展 Seq
的 WrappedArray
,如下所述:Arrays Scala Doc
但是这里:
object MyObject {
def main(args: Array[String]): Unit = {
val a = Array(1,2,3)
// val a: Seq[Int] = Array(1,2,3) if added explicitly works
val result = a match {
case Seq(
first,
second,
third
) => (first, second, third)
}
println(result)
}
}
代码失败并显示:
Error:(9, 15) scrutinee is incompatible with pattern type;
found : Seq[A]
required: Array[Int]
case Seq(
隐式转换没有发生,为什么?
最佳答案
Burak Emir 给出了在模式匹配中不允许隐式转换的语言设计决策的基本原理(以下引自 www.scala-archive.org):
1) Type checking patterns relies on static information (like everywhere else in the compiler). In the case of patterns, an "expected type" is propagated down, in order to type variable binding patterns and more generally verify that the pattern is something that makes sense. The expected type starts, of course, with the scrutinee (aka the selector expression aka what is matched upon).
2) The translation of pattern matching uses (almost) every means possible to avoid redundant type tests. This means, that the cases present in the source code get "compressed" into a sort of decision tree diagram. This later gets translated to code.
Enter implicit conversions. Having the scrutinee be of a different type then the patterns means we cannot make use of expected type in patterns. Consequently, we would have to type check patterns independently of the type of the scrutinee.
This alone might still be feasible (careful here, who can foresee hairy interactions with sequence patterns etc). We could say, patterns have a type independent of the expected type, and type checking will see whether the type of the scrutinee complies with the pattern types (possibly after applying some implicit conversion).
But this turns out to be a non-specification.
implicit def fbTypeToFoo ...
implicit def fbTypeToBar ...
fb match {
case Foo(...) =>
case Bar(...) =>
}
What seems to really be needed is to apply the views "by need", meaning "inside" the pattern match.
This clashes with the present algorithm doing task 2). In presence of implicit conversions, the task of pattern matching is in fact pushed one level deeper, as the outermost pattern will always match (there's a conversion after all). This is quite annoying to implement and to specify, because patterns with and patterns without implicit conversion from the scrutinee type might be mixed, like in
implicit def FooToBar...
myFoo match {
case Foo(...)
case Bar(... )
case Foo( ...)
}
The assumption that a top-level "Foo" would never enter the "Bar" case is now invalid (there's a conversion after all). One basically loses all hope of optimizing for the outermost level. While the current matcher would join the remainder of patterns 1 and 3, a hypothetical matcher with implicit calls could not be designed to do so, as it would violate the first match policy.
关于arrays - 模式匹配时不会发生从 Array 到 WrappedArray 的隐式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45336875/