簡體   English   中英

Scala中的模式匹配分配

[英]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

  1. (e)編譯並運行,因為Seq(1)Seq.apply(2)的快捷方式,它總是方便地給出List實例,即。 這里List(2) *。 因此,它可以與(b)情況同化。
  2. (f)出於相同的上述理由進行編譯和運行( Seq(1)給出與case List(e)匹配的List(1) case List(e)
  3. (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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM