arrays - 模式匹配时不会发生从 Array 到 WrappedArray 的隐式转换

标签 arrays scala

在此示例中:

scala> val a: Seq[Int] = Array(1,2,3)
a: Seq[Int] = WrappedArray(1, 2, 3)

发生隐式转换,Array 转换为扩展 SeqWrappedArray,如下所述: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/

相关文章:

javascript - 使用 .map 一个接一个地渲染多个状态

scala - 选项 getOrElse 类型不匹配错误

scala - 用猫创建抽象集合的有效方法

scala - 为什么这个 scala 素数生成如此慢/内存密集?

scala - 如何使用隐式转换将List [A]转换为List [B]

LINQ:实体字符串字段包含任何字符串数组

arrays - 如何在open62541中向服务器添加UA_String数组

javascript - 显示学校类(class)对象属性中的所有学生数据

javascript - 如何从数组中提取两列

java - Scala 有 floatToIntBits 和 intBitsToFloat 方法吗?