原文: DslBoundary 设计 2006年8月1日 Bliki 索引
当说起" 领域专用语言(Domain Specific Language / DSL)"这个话题时,一个常见的难题是"到底什么是DSL什么不是DSL",难就难在根本没有一个精确的定义,是与不是之间存在很大的灰色地带。
在我看来,界定一种语言是不是DSL关键是看它在范围和能力这两方面是不是受限,DSL都有自己专门适用的领域,并且缺乏通用目的语言(General Purpose Language / GPL (译注:并非GNU General Public License,下同))的某些基本特性。通常,优秀的DSL很小而且简单,因此有了"小语言"和"迷你语言"的称谓。
DSL分为内外两类。先说内部DSL,和API之间的界线很模糊,两者没有本质区别,一种内部DSL其实就是一套有个漂亮名字的API(正如老贝尔实验室流传的一句名言:"库设计就是语言设计")。尽管如此,我觉得使用体验还是不同的,当你使用一套有DSL体验的API时就能感觉得到。像 连贯接口这样的API用起来有种质感上不同的体验。另外,以DSL的视角考虑问题能给你一种改进程序可读性的新思路——充分发掘主语言的语法以创建一套自成一体的小语言—— rake就是一个绝佳的例子。
再说外部DSL,问题就成了它与GPL有哪些不同。一般而言,DSL无图灵完备性,且缺乏抽象机制,这是它区别于GPL的最明显的特征。DSL在这些方面能力受限,一个好例子是正则表达式,另一个更有趣的候选者是SQL,尽管SQL比较复杂,威力强大,但它同样既不图灵完备,也没有构建新抽象的能力。
一门语言如果图灵完备还可以划为DSL吗? Ploticus的脚本语言只用于Ploticus制图,目的清晰专一,尽管它图灵完备,但仍是一门DSL——至少我这么看。那么XSLT呢?它的目的也仅限于转换XML文档,但它的能力已经如此强大,以至于越来越多的人把它划为一门GPL。
Ploticus这个例子引出另一个问题:嵌入式语言是DSL吗?Excel的宏语言看上去和Visual Basic一样,它是DSL吗?如果一个应用程序里嵌入了一种通用脚本语言,又如何界定呢?
这个问题与区分内DSL和API相同,我认为界定的关键在于目的——既包括语言设计者的目的,也包括语言使用者的目的。例如在用XSLT时,为了在输出文档中嵌入一些值,我用了一些花哨的调用,但我的目的只是用它转换XML文档,所以我仍是把XSLT当成一门DSL。但是,如果我用它解决八皇后问题,那就是把它当成GPL了。如果XSLT的设计者认为它是一门专用于XML转换的语言,那就是把它当做一门DSL,即便有聪明人能用它做"矫情"的事。
把这些问题放开了讨论很有意思,但不能只顾着讨论而轻视了DSL的妙用。一门DSL应该设计成一门受限的语言,让它紧密聚焦在单一问题上——只要把这一点放在心头,不论你是要设计DSL还是要使用DSL,它都会成为一件有力武器。总之,它的实用性才是真正重要的。