1. 程式人生 > >話說模式匹配(3) 模式匹配的核心功能是解構

話說模式匹配(3) 模式匹配的核心功能是解構

http://www.artima.com/scalazine/articles/pattern_matching.html
這篇文章是odersky談scala中的模式匹配的一段對話,我做了部分片段翻譯(不是連貫的):

模式可以巢狀,就像表示式巢狀,你可以定義深層的模式,通常一個模式看起來就像一個表示式。它基本上就是同一類事情。
它看起來像一個複雜的物件樹構造表示式,只是漏掉了new關鍵字。事實上在scala當你構造一個物件,你不需要new關鍵字
然後你可以在一些地方用變數做站位符替代物件樹上實際的東西。

本質上,當你需要通過外部來構造物件圖,模式匹配是必要的,因為你不能對這些物件新增方法
有很多場景的例子,XML是一個,所有解析過的資料落入不同的分類。
舉例,一個標準的場合是當你用編譯器解析抽象語法樹的時候模式匹配是必要的。

解構物件 (De-constructing objects)
Bill Venners: 你說模式像表示式,但它更像“逆表示式”,不同於插入值並得到結果(構造一個物件的過程),你放入一個值,當它匹配,一串值彈出來。
Martin Odersky: 是的,它確實是反向構造,我可以通過巢狀的構造器來構造物件。我有一個方法一些引數,通過這些引數可以構造出負責的物件結構。模式匹配正好相反,它從一個複雜的物件結構中抽出原來用於構造這個物件的引數

可擴充套件性的兩個方向(Two directions of extensibility)

擴充套件性的另一個概念是資料結構相對固定,你不想改變它,但你想要用到的行為操作是開放的。你隨時都想要新增新的操作。
典型的例子是編譯器,編譯器用語法樹表達你的程式,只要你沒有改變你的語言,語法樹就不會變,一直都是同一顆樹
但編譯器想要這棵語法樹每天改變。明天你或許想到一種新的優化在遍歷樹的階段。

所以,你想採取的辦法是操作定義在你的語法樹外部,否則你要不斷的新增新方法

這個工作正確的方向,取決於你想在那個方向擴充套件,如果你想要擴充套件新的資料,你選擇經典的面向物件通過虛方法呼叫實現。如果你想保持資料固定,擴充套件新的操作,模式更適合。
實際上有一個設計模式,不要和模式匹配混淆,在面向物件程式中稱為“訪問者模式”,也可以用面向物件的方式表達模式匹配的方式,基於虛方法委派的。

但實際中用visitor模式是非常笨重的,不能像模式匹配那樣輕鬆的做很多事。你應該終結笨重的vistors,同時在現代虛擬機器技術中也證明vistor模式遠沒有模式匹配有效。所有這些原因,我想應該為模式匹配定義一套規則

ps, 前段時間王垠同學在批判設計模式的一篇文章中,提到visitor模式就是模式匹配。
可以對比一下scala語言通過case class/extractor方式在語言級別支援模式匹配,與通過visitor模式來達到同樣的效果時的程式碼差別。