[英]Pattern Matching Assignment in Scala
我在scala中通過模式匹配進行賦值有問題。 假設我有以下幾點:
a. Seq.unapplySeq(List(1))
b. val Seq(z) = List(1)
c. val c = List(1) match {
case Seq(e) => e
}
d. List.unapplySeq(Seq(1))
e. val List(a) = Seq(1)
f. val b = Seq(1) match {
case List(e) => e
}
只有(d)無法編譯,而其他(d)則可以正常運行。
我知道List的unapplySeq在SeqFactory中定義為:
abstract class SeqFactory[CC[X] <: Seq[X] with GenericTraversableTemplate[X, CC]] extends GenSeqFactory[CC] with TraversableFactory[CC] {
applySeq[A](x: CC[A]): Some[CC[A]] = Some(x)
}
因為CC是列表,所以(d)中的Seq不會進行類型檢查。
似乎(a),(b)和(c)在一組中,而(d),(e)和(f)在另一組中。
以我的理解,(f)的銷毀實際上將調用(d),因為(f)中的模式匹配所做的是使用List破壞Seq(1)。
我的問題是,在(d)無法編譯的情況下,為什么(e)和(f)仍然正確。
我可能會為您提供一個答案,而不是談論SeqFactory
:
Seq(1)
是Seq.apply(2)
的快捷方式,它總是方便地給出List
實例,即。 這里List(2)
*。 因此,它可以與(b)情況同化。 Seq(1)
給出與case List(e)
匹配的List(1)
case List(e)
) (d)不會編譯,因為我在第一點關於(e)情況的論述是關於實例而不是type ,即。 Seq(1)
是List
的實例,但類型為Seq
。 這是一個示范:
List.unapplySeq(Seq(1))
相當於
List.unapplySeq(List(1).asInstanceOf[Seq[Int]])
並給出:
*error: type mismatch;*
然而:
List.unapplySeq(List(1))
等效於:
List.unapplySeq(Seq(1).asInstanceOf[List[Int]])
兩者都給:
Some(List(1))
但是,這就是困難所在,您對(f)模式匹配的好奇心有一點了解:它的行為就像scala在內部將其鍵入為List
而不是Seq
。
這是我的解釋,模式匹配不關心輸入的類型。 就這么簡單(例如,參見https://www.scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html#variable-patterns )。 這是一個示范:
var foo: Seq[Int] = List(1)
foo match { case _: List[Int] => true } // gives true
foo = 1 to 3
foo match { case _: List[Int] => true } // throws scala.MatchError
希望能幫助到你。
*更清楚一點,如果在另一個scala實現中,通過此apply給出Vector(2)
,則錯誤不是在編譯期間彈出,而是在運行時彈出(Alexey Romanov對此做了很好的論述)。
(e)被翻譯成(f),是正確的。 但是,如果您查看https://www.scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html#pattern-sequences ,則對unapplySeq
的唯一要求是結果類型,而不是參數類型。 因此,我的猜測(該規范實際上並未指定該參數,並且我目前無法檢查)是:(f)在調用unapplySeq
之前測試其參數是否為List
,即內部類似於
Seq(1) match {
case canUnapplySeq: List[Int] =>
... List.unapplySeq(canUnapplySeq) // (d) only invoked here
}
請注意,道理也適用於unapply
為好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.