利用C++、scala等語言的運算子多載功能定製領特定領域語言(DSL,Domain-Specific Language )

來源:互聯網
上載者:User

http://hi.baidu.com/atry/blog/item/c4bc96ef7a1ac7e8cf1b3ef4.html

 

領特定領域語言(DSL,Domain-Specific Language )是近年來的熱門話題。關於DSL,有一個趨勢就是在通用語言中整合DSL。

很多年以前,我們如果要在通用語言中使用DSL,通常需要用字串,比如作資料庫訪問,就要拼接一串SQL語句。缺點有很多:a) 不自然,特殊字元需要轉義;b) 容易留下SQL注入的漏洞;c) 缺乏語法檢查,拼錯了一個單詞還要到運行時才能知道出錯,調試起來麻煩。

不 過現在是二十一世紀了。許多語言都內建了一些DSL。比如JavaScript、ActionScript等ECMAScript語言中的新特性E4X, 可以方便的使用XML和XPath。再比如說C# 3.0中的LINQ運算式,可以寫SQL查詢。這是一個很好的現象,不過本文所講的則是“定製”DSL,可以不僅僅用上語言本身提供的DSL,還能建立自 己的DSL.

這可以靠運算子多載實現。我最早接觸運算子多載是C++,這個特性原本並未打算用來設計DSL,只是希望簡化一些日常操作的 代碼,比如字串串連。不過現在是二十一世紀了。終於出現了一群變態程式員把這個特性的潛力挖掘了出來。boost中的許多庫都用運算子多載實現了 DSL,比如Boost.Xpressive(實現了Regex)、Boost.Spirit(實現了BNF範式)、Boost.Phoenix(實現了 匿名函式宣告或者說Lambda運算式)。我自己也用運算子多載實現過static_lambda,可以把一個匿名函數變成一個靜態類型的類,用到模板參 數裡面。

根據我用過的經驗,這個技術是有用的,Boost.Xpressive和Boost.Spirit都很實用。

不過用C++運算子多載實現的DSL還是有很多致命問題的:
1. C++98的模板缺少可變數量的模板參數這個特性。
2. C++98的左值右值引用的匹配有嚴重缺陷。
3. C++編譯速度太慢。
4. C++不支援重載空格。

前兩個問題是C++98的問題,再過幾年如果C++0x普及了就解決了。
第三個問題是老大難問題,估計等到太陽變成紅色巨星的時候都未必能解決。不過C++倒是有其繼承者D語言,編譯速度奇快無比,用來定製DSL倒是不錯,只不過現在用D語言做應用開發又缺乏相應的庫、IDE啥的,因而D語言開發的項目很罕見。
第四個問題會導致DSL的文法不能很乾淨,比如Regex裡面就得加入 << ,看著有點亂。這個問題運算子多載解決不了,因為運算子多載原本就沒打算還有這麼變態的功能。

不 過C++本來定位就是有進階特性的底層語言,我們做應用開發的,大多數情況還是用更上層的語言,比如Java、C#、Ruby啥的,來連連資料庫、畫畫網 頁。C++的死活於我何相干?我關心的是應用,關心怎麼在我現在的Java項目中用上內嵌的XML、SQL之類的東西。Java寫SQL用的 PreparedStatement很噁心的一點就在於我要去數問號,設一個參數還得去數數那是第幾個問號,很讓人吐血。

所以這裡我要推薦的是scala,相容Java位元組碼,也可以產生相容.net的cli,能無縫整合到現有系統。這個scala裡面就有一個資料庫連接的庫,可以內嵌SQL語句到代碼中:

object foo extends Application {

import scala.dbc._
import scala.dbc.Syntax._
import syntax.Statement._

val db = database("jdbc:postgresql://localhost/test","myUserName","")

val res = db.executeStatement {
select fields ("name" of characterVarying(50)) from "person"
}

for(val i <- res;
val f <- i.fields) {
Console.println(f.content.sqlString)
} }

這裡面的SQL語句並非語言原生支援,而是依靠庫實現的,所以很牛叉。
不過只要搞清楚實現,就知道其實一點都不牛叉,因為scala的文法裡面可以省略訪問成員用的“.”以及函數調用的括弧,所以實際上上面那一句

select fields ("name" of characterVarying(50)) from "person"

等價於

select.fields("name" of characterVarying(50)).from("person");

這隻不過就是一段函數調用而已。

雖 然這個SQL文法scala只用了一些小把戲就實現了,不過scala是個強型別的語言,運算子多載、自動推斷類型等特性它都有,而且又沒有C++那樣的 缺陷,確實很容易實現任何DSL。此外Java社區爭論了很多年的closure它早就有了,還有一大堆函數式編程的,算是Haskell和Java的混 合體吧,既可以幹Java乾的日常工作,又有小朋友們不會用的牛叉的進階特性。所以,scala是個很好玩的東西,而且比較實用,應該會有前途,值得關注。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.