2008年6月13日 星期五

蔡學鏞【言程序】部落格: F#:微軟的下一代重量級語言

蔡學鏞【言程序】部落格: F#:微軟的下一代重量級語言
在下一個版本的Visual Studio中,F#將會成為正式的一員,和C#、Visual Basic平起平坐。目前,F#也已經和Visual Studio做了初步的整合。
一個新語言的誕生,自然有它的時代背景,對F#來說,自然是函數式編程(FP,Functional Programming)的因素。我已經在許多文章提到FP對現在IT環境的重要性,請自行上網查詢閱讀這些文章,我不在此重複敘述。
事實上,除了具備FP的能力,F#在Imperative Programming與OOP(物件導向編程)方面的能力,也是不打折的。因此,利用F#寫程式,可以享有高度的自由,想用什麼樣的paradigm, 你可以自己作主。但如果完全不使用FP,那麼使用F#的意義不大,不如回頭使用C#。

雖然F#比其他FP語言(Haskell、Erlang、Common Lisp)似乎更好學(因為語法比較不奇怪),但是一般人要善用F#並不容易,主要是FP的Paradigm和我們慣用的OOP與Imperative Programming不同。因此,熟悉F#的過程中,一開始最好強迫自己只用FP的方式寫F#程式,不要用到OOP和Imperative Programming。

FP編程常用到的技巧包括了下面八點:Higher-Order Function、Currying、Lazy Evaluation、Continuations、Pattern Matching、Closure、List Processing、Meta-Programming。令人驚訝地,F#對這八點的支援都相當不錯。許多FP語言在這些方面可能還比不上F#完整。一 開始寫F#程式,盡量多用這些技巧,寧可矯枉過正,這是學習的必經階段。

OS: 這八點是啥?老實說,我也不清楚。

我認為,想要開始習慣用F#寫FP程式,你可以開始做下面的事:



  1. 將Object為主的程式碼轉回Procedure的方式:將Object化成Record,將Method轉成Function,將this(或self)當作Function的參數,把Function集中放到Module(模組)。

  2. 將程式中用到迴圈的地方,盡量轉成遞迴(Recursion)。先不要管執行效率的問題。

  3. 將程式中用到if/else或switch/case的地方,改用Pattern Matching(模式比對)。

只要做到上述這三件事,你的F#程式會具有濃濃的FP風味。


F#由於是建構在.NET平台上,所以當然和.NET有天衣無縫的整合。事實上,F#所提供的互動式環境,對於學習.NET API來說,是相當不錯的工具,比PowerShell更適合程式員使用。


由於F#的開發相當早(2002年),且F#比較是屬於靜態的語言,而不是動態的語言,所以目前F#並沒有以.NET的DLR(Dynamic Language Runtime)為平台。未來F#會不會搬到DLR上頭?情況還不明朗。


以往用FP開發的系統多以科學和財務為主,現在有了F#和.NET,應該可以為FP打開更廣的應用領域。我相信,漸漸地會有人改用F#寫.NET的各種應用(ASP.NET、GUI、LINQ)。


F# 也是一種Language-Oriented Programming(語言導向編程)的語言。所謂的「語言導向編程」,就是Meta-Programming,也就是「可以建立自己的DSL」。我寫 過一篇關於「GPL & DSL」的文章,但是這篇文章並未得到太多讀者的注意,顯然大家並沒有意識到Meta-Programming的重要性,相當可惜。


GPL與DSL

文 / 蔡學鏞

扔掉浴室裡的瓶瓶罐罐,GPL一瓶抵萬瓶。為什麼我們要推出GPL這麼好的產品?鞏利俯身彎腰,素珠側身插腰,齊聲說道:『因為你值得!』

看了上面這段廣告,如果你是個神智正常的人,應該會啼笑皆非。『GPL是什麼東東呀?這麼神奇!別把我當容易上當的傻B』… 但其實我們都曾經上當過。

GPL (General-Purpose Language,一般用途的語言)是指「可以用在許多開發領域,沒有特定用途」的語言。例如:C、C++、Java、C#、Ruby、Python都算 是GPL。在適合使用GPL的地方使用GPL,當然沒問題;但是在不適合GPL的地方使用它,事情可能一樣可以做得到,只是要花更多精力,事倍功半,且潛 在的問題會更多。

在特定的專業領域(例如GUI、資料庫、Web、統計)使用GPL,不見得很適合。如果在專業領域能改用專為該領域打造 的SPL(Special-Purpose Languag,特殊用途語言),程式會變得相當簡短,且表達力更豐富、生產力更高、也更不容易有bug。許多人也將SPL稱為DSL(Domain- Specific Language),或小語言(little language)。

對於DSL,我們其實並不陌生。SQL就是一種DSL,讓我們和資料庫管理系統(DBMS)進行溝通。SQL有自己的語法,SQL只能用來進行資料庫相關的動作,不能用來寫一般的程式,這就是相當典型的DSL。

除了SQL之外,「小語言」在UNIX上有長遠的歷史,為UNIX環境增添許多吸引力,例如Awk就是UNIX使用者愛用的小語言。近幾年引起大家關注的RoR(Ruby-on-Rails)也是一種DSL。RoR讓你不需要寫很多程式碼,就可以做出網站。

最 近許多XML應用,也都是DSL的表現,例如微軟的XAML、Adobe的MXML。這些XML都是將GPL的物件模型直接對應到XML,並未發揮太多 DSL的優點。而且由於採用「不適合人類編寫」的XML格式,因此最好搭配特別的設計工具(例如GUI設計工具)。我認為,這類XML格式的DSL,只是 一種便宜行事的作法,廠商應該要想辦法設計出更好的DSL。

如何設計出DSL?不同的GPL對此有不同的作法,例如REBOL、Ruby、Common Lisp、Curl、PowerShell、Groovy都號稱讓你可以設計自己的DSL,但是它們對於DSL的支援程度,以及DSL的語法彈性,卻大大地不同。

如 果某GPL允許方便地自訂DSL,我們說這種語言支援meta-programming。即使一個語言沒有支援meta-programming,它依然 可以做出DSL,只是 (1) 會相當辛苦,要自己寫剖析器(parser),或者 (2) 做出來的DSL,彈性相當差。例如:在C++/MFC時代,有所謂的事件發派巨集(event dispatch macro),我也認為它是一種DSL,只是囿於C/C++的巨集威力有限,所以此「事件發派巨集」的彈性相當糟糕。

不要因此對巨集留下不好的印象。許多語言(包括Curl和Common Lisp)的巨集具有很強的DSL功能,可不像C/C++的巨集這麼陽春。

除 了巨集之外,也常見使用外部的語言和工具,來設計DSL。例如ANTLR讓我們用文字描述方式,定義自己的DSL,它會幫我們產生Parser。或者,你 也可以使用微軟推出的DSL工具,以繪圖的方式,描述DSL的語法。外部定義DSL的作法,或許可以產生不同GPL的剖析器。

如果DSL和GPL的資料和程式完全不能流通,那就沒什麼意思了!畢竟開發應用時,我們必須以GPL為主,特殊的地方才用DSL,兩者之間最好沒有隔閡。

所以,某GPL對於DSL的支援良窳,我的三個基本的判斷原則是: (1) 能否輕易地設計DSL (2) 能否設計出有彈性的DSL (3) 能否讓DSL和GPL使用上合為一體。在未來的編程環境,具有良好了DSL支援,絕對是一大加分。

除 了文章一開始的萬用洗髮精之外,瑞士刀也適合用來比喻GPL。瑞士刀有很多功能,但是我想除了馬蓋先之外,我們還是喜歡用各種不同的刀子,去做不同的事。 職場講究專業分工,不同才能的員工各司其所。語言也應該專業分工,別再讓通才語言做專才語言的工作,這才是未來軟體開發該走的路。

沒有留言: