利用C++、scala等语言的运算符重载功能定制领域特定语言(DSL,Domain-Specific Language )
2011-05-14 14:20
323 查看
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(实现了正则表达式)、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的语法不能很干净,比如正则表达式里面就得加入 << ,看着有点乱。这个问题运算符重载解决不了,因为运算符重载原本就没打算还有这么变态的功能。
不 过C++本来定位就是有高级特性的底层语言,我们做应用开发的,大多数情况还是用更上层的语言,比如Java、C#、Ruby啥的,来连连数据库、画画网 页。C++的死活于我何相干?我关心的是应用,关心怎么在我现在的Java项目中用上内嵌的XML、SQL之类的东西。Java写SQL用的 PreparedStatement很恶心的一点就在于我要去数问号,设一个参数还得去数数那是第几个问号,很让人吐血。
所以这里我要推荐的是scala,兼容Java字节码,也可以生成兼容.net的cli,能无缝集成到现有系统。这个scala里面就有一个数据库连接的库,可以内嵌SQL语句到代码中:
这里面的SQL语句并非语言原生支持,而是依靠库实现的,所以很牛叉。
不过只要搞清楚实现,就知道其实一点都不牛叉,因为scala的语法里面可以省略访问成员用的“.”以及函数调用的括号,所以实际上上面那一句
等价于
这只不过就是一段函数调用而已。
虽 然这个SQL语法scala只用了一些小把戏就实现了,不过scala是个强类型的语言,运算符重载、自动推断类型等特性它都有,而且又没有C++那样的 缺陷,确实很容易实现任何DSL。此外Java社区争论了很多年的closure它早就有了,还有一大堆函数式编程的,算是Haskell和Java的混 合体吧,既可以干Java干的日常工作,又有小朋友们不会用的牛叉的高级特性。所以,scala是个很好玩的东西,而且比较实用,应该会有前途,值得关注。
领域特定语言(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(实现了正则表达式)、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的语法不能很干净,比如正则表达式里面就得加入 << ,看着有点乱。这个问题运算符重载解决不了,因为运算符重载原本就没打算还有这么变态的功能。
不 过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是个很好玩的东西,而且比较实用,应该会有前途,值得关注。
相关文章推荐
- DSL Domain-specific language 领域特定语言/领域专用语言
- DSL Domain-specific language 领域特定语言/领域专用语言
- [2017-08-25]100行CSharp代码利用dynamic写个DSL(特定领域语言)
- dsl领域特定语言
- 《Groovy极简教程》第8章 Groovy:领域特定语言(DSL)
- 领域特定语言DSL
- 使用Antlr开发DSL(领域特定语言)-java
- 领域特定语言DSL
- 走近“领域特定语言”(Domain-Specific Languages)
- DSL:领域特定语言学习笔记 一
- ★软件架构DSL领域特定语言初探[
- 如何设计一门语言(十)——正则表达式与领域特定语言(DSL)
- Kafka Streams开发人员指南之流领域特定语言(Streams DSL)
- 走近“领域特定语言”(Domain-Specific Languages)
- 正则表达式与领域特定语言(DSL)
- 基于领域特定语言(DSL)的用例驱动开发(UDD)
- [导入]Visual Studio 2005 Team Edition软件架构系列课程(4):模型驱动开发的领域特定语言(Domain Specific Language )工具
- Kotlin领域特定语言(DSL)
- 用Ruby 创建领域特定语言(DSL)
- 闭包在DSL中的应用,领域特定语言的笔记