2011-12-26 36 views
7

在「在Scala編程(第二版)」在410頁,你可以找到類模擬這有以下方法:在Scala中使用模式匹配時真的很簡單嗎?

private def next() { 
    (agenda: @unchecked) match { 
    case item :: rest => 
     agenda = rest 
     curtime = item.time 
     item.action() 
    } 
} 

我很好奇,爲什麼Odersky的實現了這個與模式匹配,而不是就這樣:

private def next() { 
    val item = agenda.head 
    agenda = agenda.tail 
    curtime = item.time 
    item.action() 
} 

模式匹配如此高效以至於根本無關緊要嗎? 或者它只是不完美的例子?

回答

9

一般情況下我按照你的方式寫下來。 (雖然模式匹配是相當有效的,它並不像頭/尾高效。)如果

  1. 你想練的模式匹配
  2. 你想要一個MatchException而不是NoSuchElementException你會使用模式匹配
  3. 稍後您將要填寫其他情況。
4

有幾個方面的原因:

  1. 書的點之一,就是讓你在斯卡拉(功能)的角度思考;模式匹配是功能編程的等價物。

  2. 模式匹配和函數式方法是Scala中的自然模式,並允許像自然方式的併發這樣的事情;學習該模式,您的Scala程序將準備好進行更高級的使用。

3

模式匹配在Scala中更具慣用性,更容易保護您免受邊界條件的侵害。

在代碼

private def next() { 
    val item = agenda.head 
    agenda = agenda.tail 
    curtime = item.time 
    item.action() 
} 

兩個agenda.headagenda.tail將拋出一個NoSuchElementException異常,如果agenda是一個空的列表,所以使它的實際工作,你需要添加一個檢查了點。

模式匹配版本其實也有類似的問題(如日評論指出),但我發現修復清潔劑,因爲所有你需要做的就是添加另一種模式:

private def next() { 
    (agenda: @unchecked) match { 
    case item :: rest => 
     agenda = rest 
     curtime = item.time 
     item.action() 
    case _ => {} 
    } 
} 
+0

模式匹配版本將拋出MatchException如果模式不匹配 – gerferra 2011-12-26 19:43:07

+0

@gerferra:我認錯。但是無論如何,模式匹配版本都有一個簡單的解決方法。我會更新答案。 – 2011-12-26 20:01:11

+3

另一個版本也有一個簡單的解決方法:或者換成if(!agenda.isEmpty),或者使用'agenda.headOption.foreach {item => agenda = agenda.tail; curtime = item.time; item.action()}' – 2011-12-26 22:47:50

0

我的猜測是第一個例外是不是一個擔心,在這個「下一個」方法被調用之前可能會有一些檢查。實際上,這可能也是「未經檢查」註釋的原因,所以他可以不必額外增加case _ =>。我認爲他的推理更多的是他想用「不適用」。這裏的另一種無模式匹配,也沒有headtail可能是這樣的:

private def next() { 
    val item :: rest = agenda 
    agenda = rest 
    curtime = item.time 
    item.action() 
}