2011年4月28日 星期四

20. Scala 的企圖心,也是它的特性 --Pattern Matching

在 Java 中你應該使用過 switch 這個命令,但只能比較整數類型,Java 7 會要支援 String 的比較,讓 switch 命令更加好用。但比起 Scala 的 Pattern Match,就算小巫見大巫。

Pattern match 的來源,絕對不是 switch,它其實是出自於 functional language 的特性。
回想我們寫數學函數時,常會遇到「若參數是什麼就如何,不是的話又是如何」,這引導出pattern match。

以下以費伯納西數列舉例,什麼是費伯納西數列,簡單的講就是後面的值等於前兩個值的相加,但第一個值是1,第二個值也是1。
所以費伯納西數列:1, 1, 2, 3, 5, 8, 13, ...

如何製作費伯納西數列?你在一些函數式語言中,可能會有這樣的寫法(此為虛擬碼,不要問我這是什麼語言)

function fib(1) = 1
function fib(2) = 1
function fib(n) = fib(n - 1) + fib(n-2)

第一行指令,說明fib(費伯納西)這個函數,參數 1 時,值為 1
第二行指令,說明fib(費伯納西)這個函數,參數 2 時,值為 1
第三行指令,說明fib(費伯納西)這個函數,參數 n 時,值為前面兩個值的相加

請注意!這三個指令已經將要做的事做完了,不需在那裡 loop 。
這就是函數式語言的概念,是不是很像前面用口語敘述的方式。

「這跟 pattern match 有什麼關係?」
在前面函數式語言的三個 fib 定義中,我們個別定義參數是1, 2,  n時  fib 應該如何做。
當執行時,呼叫到 fib 的函數,那時會有一個真實參數,函數式語言將會使用真實參數,逐一與各 fib 定義中的參數比對,找出符合的 fib 定義,找到後執行該 fib。
使用真實參數,逐一比較各個 function 的參數,這就是 pattern match。

「等等,這不還是與 switch 功用相類似嗎?有多稀奇?我用 switch 也可以做得到!」

嗯嗯,確實,費伯納西的參數是整數,難怪可以使用 switch 取代。
那再來另外一個例子,假設你要寫一個 greeting 的功能
1. 對於你的好友 John 要說 "John 你好"
2. 對於女士要說 "Miss " + name + " 你好"
3. 對於男士要說 "Mr " + name + " 你好"
4. 對於鴨子要說 "呱呱"

你該怎麼做?準備 「if 來 if 去」來個 if 大作戰了嗎?

看看函數式語言如何做!
function greeting("John") = "John 你好"
function greeting(isMiss(name)) = "Miss " + name + " 你好"
function greeting(isMr(name)) = "Mr " + name + " 你好"
function greeting(duck: Duck) = "呱呱"
乾淨俐落!

上面的例子也是使用參數比對來製作。從這個例子,你可看出函數式語言的參數比對,可以非常的複雜。不僅比對值,還可以比對 List,比對型態,運用非常廣泛,絕非 switch 這麼簡單的命令可比擬。

看到此,你不需急著去學習函數式語言,Scala 的 pattern match 也可做到相類似的功能,同樣可以比對值、比對 List、比對型態,也因此 pattern match 才會被列為 Scala 的超強特性。

對於 pattern match,這裡不會深入介紹,這裡只是讓大家知道有這一回事。

順帶一提 Scala 中只有 pattern match 並沒有 switch,不要誤用了。

沒有留言:

張貼留言