2013-07-23 71 views
2

我是新來的scala,當研究模式匹配部分時,我感到困惑。模式匹配,「::」不應用混淆

val hd::tail = List(1,2,3,4,5) 

執行該代碼後,HD將INT = 1,和尾部將列表[INT] =列表(2,3,4,5)。 這碼等於:

val ::(hd,tail) = List(1,2,3,4,5) 

我瞭解到,這個代碼是模式匹配,它實際上調用不應用方法。 但是,當我以這種方式編寫代碼,編譯錯誤:

val result = ::.unapply(List(1,2,3,4,5)) 

它說,方法參數類型不匹配。 「::」的不適用方法需要「:: [?]」

有誰知道原因?

+0

這可能是因爲'(HD,尾),'是不是有效標識符。 – kingdamian42

回答

4

的類型不匹配錯誤是因爲::.unapply需要的::[T]一個實例,而不是更普通型List[T]的一個實例。 Scala會自動添加匹配的實際類型。 換句話說,我的理解是,當你這樣做:

val list = List(1,2,3,4,5) 
val hd::tail = list 

編譯器生成到這一個類似於:

val list = List(1,2,3,4,5) 
val (hd, tail) = 
    ::.unapply(
    // First match to test against input type 
    // (necessary as the static type of `list` is `List[Int]` 
    // so we don't know until runtime if it is an instance of `::[Int]` 
    // or an instance of `Nil`) 
    list match { 
     case nonEmptyList: ::[Int] => nonEmptyList 
     case _ => throw new MatchError 
    } 
) match { // Second match to test against result of `::`.unapply 
    case Some(result) => result 
    case _ => throw new MatchError 
    } 
+0

+1的細節,ty。兩場比賽可以合併爲一個嗎? 'case Some(nonEmptyResult::: [Int])=> nonEmptyResult' –

+0

Accepted。但我仍然想知道這種編譯器生成適用於所有模式匹配還是僅適用於List情況? – cloud

+0

永遠。只要靜態輸入類型是'unapply'的預期類型的​​子類型,就一定需要運行時類型檢查。 –

1

您擁有的方法簽名不正確。 ::是一個案例類,所以不適用需要::的實例。這裏的東西更接近你可能會尋找,但通常我不代碼,因爲它的模式匹配方案的完成呼叫unapply

//Note the type returned by unapply 
    val unappliedOption:Option[(Int, List[Int])] = ::.unapply(::(1, List(2, 3, 4, 5))) 

    val (hd, tail) = unappliedOption.getOrElse((1, Nil)) 

在模式匹配unapply自動爲您調用。還要注意,::是一個非空列表,雖然它仍然返回option。所以對於List一個實例,我們有兩個選擇::Nil

List(1, 2, 3, 4, 5) match { 
    case hd :: tail => println(hd, tail) // calls ::.unapply and returns hd tail if the option is Some 
    case hd => println(hd) //Default case Nil 
    } 
+0

感謝您的回答!我想知道模式匹配的理論。書中說實際上模式匹配調用不適用的方法。所以我的問題中的3行代碼應該是相同的,但第三次編譯失敗,這讓我非常困惑。 – cloud

+0

'::。unapply'需要一個案例類'::'。在你的例子中,你給它一個'List',它可以是空的,而不是非空的'::'。在任何情況下,'unapply'類都會獲取case類的實例,以便您可以找回case類中包含的內容。如果您查看'::'的定義,它會擴展'List',就像'Nil'擴展'List'一樣。 – Noah

+0

那麼爲什麼第一行和第二行代碼工作?他們是不是也用List來稱呼不適用的方法? – cloud