Match expression 有時會叫 pattern match,是一個非常繁雜的東西,在這裡我們無法全面將 match expression 講清楚,待一些相關的知識補足之後,我們會回頭再將說明仔細。本篇只會說明 match expression 的意義,以及大致的用法。
在「Scala 的企圖心,也是它的特性 --Pattern Matching」我們提及,pattern match 用在參數比對,找尋一個符合的 function 定義。
那時的例子我們定義一個 fib 函數,但依照參數不同,有不同的定義。同一個函數,有多個定義,這種方式通常會出現在純函數式語言,讓你用「比較像數學的方式」來定義函數。
在非純函數式語言,通常不使用同一函數多重定義的方式,而是在該函數定義中,直接對參數做分類,將符合的程式碼撰寫在比對之後。Scala 就是使用這樣的方式。
讓我們看例子會比較清楚。
原來在該文中,費伯納西數列的例子如下:
function fib(1) = 1
function fib(2) = 1
function fib(n) = fib(n - 1) + fib(n-2)
在 Scala 我們使用 match expression,將三個情況寫在同一個 function 中。
在 Scala 的對應程式碼如下
def fib(n: Int): Int = n match { // fib 因為使用到 recursion,所以 fib 函數需要宣告 return type case 1 => 1 case 2 => 1 case _ => fib(n - 1) + fib(n - 2) }我們仔細與前面 function fib 程式碼比對,是不是除了把三個函數寫在一起外,其他的部份幾乎一模一樣。
我們看實際執行情況
前面程式中的 n match {...} 就是 match expression。
Scala 中 match expression 的格式:var_name match {
case match_1 => match_1 相對應的程式碼
case match_2 => match_2 相對應的程式碼
....
case _ => 所有都會對應的程式碼
}
我們把 match expression 的重要部份,一個個說明如下
- match expression 使用 var_name match 帶頭,後面加上一個使用大括號括起來的程式碼。該段程式碼由一個個 case 子句所構成。
- 一個 case 子句,代表一個比對。case 子句比對的對象,沒有限制一定是要整數,任何型態都可比對,甚至我們可以比對不同的型態。
- 上例中,最後一個 case,所對應的是 _,代表所有狀況都滿足。
- underscore _ 我們之前曾經遇到過,用於變數的初始值,當時代表使用系統的初始資料。
- underscore _ 是 Scala 的「預定萬用字元」,代表的意思就是那個「預定的東西」。用在 match expression 的意思是,所有的東西都與 _ underscore 符合。若以 Java switch 來看,就是那個「default」的 case。
- match expression 比對的方式,是由第一個 case 開始比對起,一直往下比對,直到比對到一個符合的 case。找到符合的之後,就不會再比對之下的 case。
- 找到符合的 case,會執行對應的程式碼,然後結束。
- 若沒有找到符合的 case,會產生 MatchError。
- Match expression 的 result value,是最後一個執行到的 statement,也就是符合的 case 子句的 result value。
Match expression 不僅僅可以比較值,也可以根據不同的參數型態,做不同的事情。
範例
def f(x: Any) = x match { case n: Int => println("Int! n = " + n) // 若是 Int case s: String => println("String! s = " + s) // 若是 String case _ => println("Unknown! x = " + x) }實際執行情況
你若熟悉 Java 應會為上面的例子,感到震驚,實在是強了!
讓我們舉最後一個例子,同樣出現在「Scala 的企圖心,也是它的特性 --Pattern Matching」中。
假設你要寫一個 greeting 的功能
1. 對於你的好友 John 要說 "John 你好"
2. 對於女士要說 "Miss " + name + " 你好"
3. 對於男士要說 "Mr " + name + " 你好"
4. 對於鴨子要說 "呱呱"
當時函數式語言的舉例寫法
function greeting("John") = "John 你好"
function greeting(isMiss(name)) = "Miss " + name + " 你好"
function greeting(isMr(name)) = "Mr " + name + " 你好"
function greeting(duck: Duck) = "呱呱"
使用 Scala 我們會如何做呢,以下就是範例
//先準備 isMiss 與 isMr function def isMiss(name: String) = name match { case "Mary" => true // 這裡我們只 demo Mary 是 Miss 的情況 case _ => false } def isMr(name: String) = !isMiss(name) // 定義 Duck class class Duck // 定義 greeting def greeting(x: Any) = x match { case "John" => "John 你好" case x: String if isMiss(x) => "Miss " + x + " 你好" case x: String if isMr(x) => "Mr " + x + " 你好" case duck: Duck => "呱呱" } //測試 println(greeting("John")) println(greeting("Mary")) println(greeting("Jason")) println(greeting(new Duck()))實際執行
執行結果,就如同我們想像的一樣,這個 match expression 真的不愧有殺手級的能力。想想看,如果使用 Java 要做到功能,你要花多少功夫?!
既然 match expression,這麼的強大,想當然爾,Java 的 swtich 就沒有留存的必要,所以,在 Scala 中很自然的被移除了。
這樣功能的 match expression 你滿意嗎?可是還沒完,match expression 還有更好用的能力,未來我們會更加詳述。
沒有留言:
張貼留言