標籤:

為什麼 pattern matching 常常出現在函數式編程語言?

Pattern matching(模式匹配,What is "Pattern Matching" in functional languages?)基本上成為了現在 functional programming language 的標配了,不管是 Haskell、OCaml、Erlang 還是 Scala 都將其作為最常用的一個特性,而且語法都非常相似。但是在傳統的指令式編程語言中卻很少有原生的類似 pattern matching 的這種東西存在。

我實際寫代碼的背後似乎也確實發現 pattern matching 在函數式編程的時候特別舒服,但是還是沒有對背後原因的理解。從根本上講,為什麼 pattern matching 常常和函數式編程語言聯繫在一起呢?


pattern matching要和algebraic data type結合才好用,tuple、record之類。沒有此類結構的語言,有匹配也沒處用。

python有tuple,所以可以寫: (a, (b, c), d) = (1, (2, 3), 4)

rust的enum和struct都能在賦值和條件語句里使用模式匹配

所以說這和是否函數式關係不大,有沒有algebraic data type才是關鍵


歷史和技術原因

歷史原因:

最初,Scheme/ML等語言是沒有pattern matching的。70年代Hope語言首先使用Pattern、ADT後,迅速被ML、Miranda等語言引入,此後自然地被Ocaml/Haskell等繼承並不斷發展。或許是函數式語言本身沒有引起工業界「主流用戶」的足夠重視,而使得pattern matching/adt在命令式/函數式語言也沒流行起來。

技術原因:

pattern matching/adt的實現並不那麼簡單,經過多年的努力,在FP語言中得到充分發展。

1. pattern mathing的效率:

參看下面的文章:http://synrc.com/publications/cat/Functional%20Languages/L/match/jun08.pdf

新語言如Elixir的pattern maching可能優化不夠,常常有「不如直接if-else效率高」的感覺,這也是正常現象。。

2. pattern和OO、命令式:

Pattern matching的正確性檢測(類型檢查、模式是否窮盡等)依賴於語言自身的類型系統。

比如這個由於Java的「泛型」給Scala帶來的問題:How do I get around type erasure on Scala? Or, why can"t I get the type parameter of my collections?

ADT伴隨著內存分配-釋放,為了看起來自然,不該有顯示的new,於是可以增加關鍵字(如scala的case class);為了回收方便,最好要有GC,而且其優化要從functional data的角度考慮。在FP未收到足夠重視前,主流面向對象語言也不太可能為它去做什麼改變。


可能和歷史沿革有關:研究函數式語言的往往更注重語言本身的能力,而非編譯期的優化。


Scala的case class使用pattern match來處理複雜數據結構非常自然。比如用使用case class來抽象JSON數據格式,對具體數據的處理使用pattern match的方法。這裡有一個小例子Cousera 響應式編程


普通語言:

enum Fuck {
Shit,
Bitch,
Frog,
}

var goddam = Frog;

var older = match goddam {
Shit =&> "翔",
Bitch =&> "表",
Frog =&> "蛤",
}

文藝語言:

enum List {
Nil,
Cons (T, List),
}

let loli = Cons("大", Cons("哥", Cons("哥", Nil)))

function display(loli: List) {
match loli {
Cons(car, cdr) =&>
print(car); display(cdr);
Nil =&> print("()");
}
}

在沒有強大的類型系統的情況下,模式匹配我覺得和 switch 沒什麼區別誒……

這是 @唐生 的答案的補充。


1. 開發效率高。用Scheme這種沒有模式匹配的語言寫一點稍微複雜點的代碼,處理數據結構變得很啰嗦,各種條件分支一層一層的let去bind一個結構的各個部分;而用模式匹配一次完成一種情況,清晰明快。

2. 執行效率高。編譯器能對一組模式匹配優化產生最優代碼,還能警告漏掉的情形。FP本來執行效率就弱,難得有這種沒什麼毒副作用的提高效率的方法。


推薦閱讀:

python協程是什麼?
為什麼會有函數式編程?
函數式編程能否解決所有經典的演算法問題?
想要理解函數式編程的思想,最好用哪種函數式編程語言入門?
Scheme語言中的「不可變數據」會產生性能問題嗎?

TAG:函數式編程 |