模式匹配并不是什么新功能。而事實(shí)上它和函數(shù)式編程也沒(méi)有什么太大的關(guān)系。它之所以常常被認(rèn)為是FP的一個(gè)特性,是因?yàn)樵诤瘮?shù)式語(yǔ)言已經(jīng)支持模式匹配很長(zhǎng)一段時(shí)間后的今天,指令式語(yǔ)言是還沒(méi)有這個(gè)功能。
還是直接用例子來(lái)看看什么是模式匹配吧,這是一個(gè)用Java寫(xiě)的Fibonacci函數(shù):
int fib(int n) {
if(n == 0) return 1;
if(n == 1) return 1;
return fib(n - 2) + fib(n - 1);
}
再看看用我們基于Java修改過(guò)的新語(yǔ)言寫(xiě)出來(lái)的Fibonacci函數(shù),這種新語(yǔ)言就支持模式匹配:
int fib(0) {
return 1;
}
int fib(1) {
return 1;
}
int fib(int n) {
return fib(n - 2) + fib(n - 1);
}
區(qū)別在哪里呢?在于后者的編譯器替我們實(shí)現(xiàn)了程序的分支。
這有什么了不起的?確實(shí)也沒(méi)什么。只是有人注意到很多函數(shù)中有非常復(fù)雜的switch結(jié)構(gòu)(對(duì)于函數(shù)式程序而言更是如此),于是想到如果能把這層結(jié)構(gòu)也抽象化就更好了。然后就把這個(gè)復(fù)雜的函數(shù)拆分成若干新的函數(shù),并在這些函數(shù)的某些參數(shù)中應(yīng)用模式(這和重載有點(diǎn)類似)。這樣依賴當(dāng)這個(gè)函數(shù)被調(diào)用的時(shí)候,編譯器會(huì)在運(yùn)行時(shí)將調(diào)用者傳入的參數(shù)與各個(gè)新函數(shù)的參數(shù)定義進(jìn)行比較,找出合適的那個(gè)函數(shù)來(lái)執(zhí)行。合適的函數(shù)往往是參數(shù)定義上最具體最接近傳入?yún)?shù)的那個(gè)函數(shù)。在這個(gè)例子中,當(dāng)n為1時(shí),可以用函數(shù)int fib(int n),不過(guò)真正調(diào)用的是int fib(1)因?yàn)檫@個(gè)函數(shù)更具體更接近調(diào)用者的要求。
模式匹配一般來(lái)說(shuō)要比這里舉的例子更加復(fù)雜。比如說(shuō),高級(jí)模式匹配系統(tǒng)可以支持下面的操作:
int f(int n < 10) { ... }
int f(int n) { ... }
那么什么情況下模式匹配會(huì)有用呢?在需要處理一大堆程序分支的時(shí)候!每當(dāng)需要實(shí)現(xiàn)復(fù)雜的嵌套if語(yǔ)句的時(shí)候,模式匹配可以幫助你用更少的代碼更好的完成任務(wù)。我所知道的一個(gè)這樣的函數(shù)是標(biāo)準(zhǔn)的WndProc函數(shù),該函數(shù)是所有Win32應(yīng)用程序必須具備的(盡管它經(jīng)常會(huì)被抽象化)。模式匹配系統(tǒng)一般都可以像匹配簡(jiǎn)單數(shù)值一樣匹配數(shù)據(jù)集合。舉個(gè)例子,對(duì)于一個(gè)接受數(shù)組作為參數(shù)的函數(shù),可以通過(guò)模式匹配數(shù)組中第一個(gè)數(shù)字為1并且第三個(gè)數(shù)字大于3的輸入。 模式匹配的另外一個(gè)好處是每當(dāng)需要添加或者修改程序分支時(shí),再也不用面對(duì)那個(gè)龐大臃腫的函數(shù)了。只要添加(或者修改)相關(guān)的函數(shù)定義即可。有了模式匹配就不再需要四人幫的很多設(shè)計(jì)模式了。程序分支越多越復(fù)雜,模式匹配就越有用。而在習(xí)慣使用這一技術(shù)之后,你可能會(huì)懷疑沒(méi)有它你一天都過(guò)不下去了。
更多建議: