知识大全 在CLR之上的构建领域特定语言
Posted 语言
篇首语:休言女子非英物,夜夜龙泉壁上鸣。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 在CLR之上的构建领域特定语言相关的知识,希望对你有一定的参考价值。
在CLR之上的构建领域特定语言 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
最近领域特定语言(DSL Domain Specific Languages)这个话题比较热门 这可以从Rails现象中看到 Rails的流行以及Rails上广泛使用的领域特定语言(从现在起叫DSL) 已经引起了对DSL的广泛兴趣 到现在为止开发人员有这样的印象 建立一个DSL 你需要专业的编译器理论知识 理解Lex和Yacc的内部工作原理并需要投入大量的时间来构建DSL 结果是极少数人愿意去尝试 他们都是从头开始构建自己的语言 这往往是成本高昂 同时 动态语言的爱好者可以毫不费力的利用他们喜欢的动态语言的动态特性来构建领域特定语言 事实上 他们中的许多以这种方式构建的任何应用程序 都有着显著的复杂性 这两种方法的差别有重要意义 第一种方式是创建属于自己的语言 就是所谓外部的DSL(External DSL) 这是一个耗资巨大的项目 因为一切都要从头开始构建 需要考虑运算符的优先级规则 运行时类库 执行代码 错误处理和I/O 第二种方法是利用和修改宿主语言 就是所谓内部的DSL(Internal DSL) 这些都容易构建和维护 你只需要考虑如何修改 所有的其它东西(通常是你不用关心的)都已经被宿主语言处理了 另一种做法是构建连贯接口(Fluent Interface) 把它叫做DSL 我认为这不是一种DSL 这种方法往往在语言的自由性方面受到很大的限制 Java和C#就是很好的例子 包括 Java 和C# 你可以列举许多语言方面的API 但这不能让我觉得这是一个DSL 在任何情况下 我的个人偏好是使用具有很高语法灵活性的内部DSL 因为我基本上都是在CLR上工作 我想利用运行在这个平台上的宿主语言 它可以让我重用大部分的使用CLR的知识 不要低估这方面的好处 在你的手中有一个熟悉的环境是非常重要的 在深入语言之前 看看究竟什么是 高语法灵活性的语言 怎么样?为内部DSL提供一个良好的宿主环境的语言需要具有哪些特性? 我需要有合适的手段来表达我的想法 这可以通过有启发性的命名 表达特定域的概念 并通常和通用语言的做法不一样 你希望能够创建一个第四代语言 这很容易做到 让我们从一个我们电子表格所使用的脚本这样简单的DSL开始如何? 你的任务就是创建乘法网格
for x in range( ): for y in range( ):
cell[ x+ y+ ] = x * y
formula x sum( x x )
这是不是真的令人印象深刻呢?这和编程语言几乎完全一样 代码也是微不足道 除了和用Excel的自动化API做一样的工作外 更简短 注意到这就是我们所用到的所有代码 我们不需要一个类的定义 或者是一个主方法 这是一个没有任何语法包袱的可执行的DSL脚本 如果前面的例子没有给你留下深刻的印象 看看如何定义订单折扣的业务规则
apply_discount_of percent:
when order Total > and customer IsPreferred
when order Total > suggest_registered_to_preferred:
when order Total > and not customer IsPreferred
这看起来和编程语言有很大不同 它更像业务分析师在Word文档中定义的业务规则 从我的角度来看 上面两个例子都是领域特定语言 他们只是表达领域的方法和风格不同 这两个例子 我们实际上已经从语言中移除了和我们的领域没有直接关系的东西 这使得我们可以专注于域 并希望有良好的工具来处理 除了域概念以外 没有任何东西可以和具有与域相匹配的语法是一样重要的 当我们开始在CLR上研究高语法灵活性的语言的时候 我们有很多的选择 我们来评估几个语言 我们将从几个来自微软的语言开始 C# —— 这是一个非常刚性的语言 类型定义 没有独立的方法/代码块 僵硬的语言 所有这些特性使得C#不是一个DSL宿主语言的好选择 他也可以做到的 但它不如其他方法 VB Net —— 其实VB Net更适合面向对象的语言 因为它使用了许多英文单词作为关键字和操作符 令人遗憾的是它也是一个非常冗长的语言 我们要减少冗余性适合我们的域概念 JScript —— 这可能引来一片笑声 但是JScript是一个非常灵活的语言 为许多事情提供了较好的语法 只要去看看所提供的所有Javascript类库 JScript提供了和Javascript相同的基础功能 虽然这样 有一点不得不考虑的是你可以做到像JQuery或 Prototype那样多大的灵活性 然而它不够成熟 我不确定将来是什么样子的 虽然它在很多方面有灵活的语法 给人有种编程语言的感觉 这会让我在一个DSL中觉得分心
F# —— 这是一门由微软开发的 将来会发布的函数式编程语言 F#支持面向对象编程 我已经简略的浏览过这门语言 虽然F#的强大功能令人印象深刻 从我的角度来看 它看起来是BNF「译者注 BNF Backus Naur Form的缩写 巴科斯范式一种使用形式化符号来描述给定语言的语法 」定义 其他什么都不像 毫无疑问这是由于作者缺乏函数式编程语言经验方面的问题 但是我不只是考虑它的可读性 我们已经看完微软开发的语言 让我们看得更远些 据统计去年CLR上运行的语言超过了一百种 所以我选择了两种我认为是DSL宿主语言的候选语言 Nemerle是一个多范型的语言(面向对象和函数式) 完全支持编译器宏(后来更多的是Lisp的变种 而不是C++) 以及许多其他的东西 这使得它是一个DSL很好的宿主语言 这不是我阅读Nemerle代码的简单理由(经常是这样) Boo是一个基于Python语法的静态类型的面向对象的语言 它支持宏(也是Lisp变种) 有一个开放的编译器管道和更容易构建DSL的特性 Boo是我首选的用于构建DSLs的语言 但是为了保证客观性 我们需要在讨论这个主题之前证明Boo有多么的强大 动态语言运行时(DLR)怎么样呢? 到目前为止我还没有讨论动态语言运行时 这是一个在CLR之上支持动态语言的微软项目(目前支持Ruby Python和EcmaScript) 更具体的来说 当人们讨论DLR的时候 他们是在讨论IronRuby和IronPython Ruby是一门被证明非常适合写内部DSL的语言 在CLR上运行可以使我们在熟悉的环境下工作 使用DLR作为一个DSL的平台当然是可能的 但是我至少在一段时间内不使用它 DLR和IronRuby本身都还是在开发之中 我不认为微软对发布日期会有任何的承诺 此外我没有发现Ruby能做的Boo做不了 我觉得Boo的元编程基础功能非常自然和强大 自然和非常强大 是什么意思? 让我们深入一点考查Boo 我说它有一个开放的编译器 我并不是指它是开放源代码的(它是 但是和这个无关) 我的意思你有办法深入到编译器的内部和在编译的时候打乱编译器的内部对象模型 这意味着我们可以以一种有趣的方式改变编译器的行为 上面的两个代码示例都是Boo的DSL代码 全面深入Boo的元编程基础功能超出了本文的范围 但是我可以用一个简单的例子来展示它的威力 CLR已有IDisposable的概念并配合using语句使用 现在我定义一个ITransactionable 将用它来定义一个事务的声明
public interface ITransactionable:
def Dispose():
pass
def Commit():
pass
def Rollback():
passmacro transaction: return [|
tx as ITransactionable = $(transaction Arguments[ ])
try:
$(transaction Body)
tx Commit()
except:
tx Rollback()
raise
finally:
tx Dispse()
只需要这个代码 我们就可以作为一个头等语言要素来使用该事务的声明了(实际上 这也正是using语句在Boo的实现方式) transaction GetNewDatabaseTransaction() DoSomethingWithTheDatabase() 现在 如果代码里面的事务抛出了一个异常 事务将自动回滚 如果它执行是成功的 事务就自动提交
不过这只是使用Boo的一个示例 并注意这里我介绍的唯一一个概念就是宏和有趣的符号[||] 没有更深入的讨论 这指示编译器在事务块内部的代码用宏的内容做了一个代码的替换 很重要的是这已经超越文本替换 我们直接修改AST(Abstract Syntax Tree 抽象语法树——编译器对象模型) 这是一个微不足道(但很强大)的例子 我们下面将探讨一个更复杂的场景 这将告诉我们为什么这样的区分是重要的 为了构建一个DSL 这个级别的功能还是不够的 你可以只使用Boo语言的语法而不使用元编程功能 类似于Ruby 有很多可选的语法 这在很多场景是非常有用的 举个例子来说 我们可以不通过元编程创建相同的语法 但是利用Boo的这一特性 如果方法的最后一个参数是一个委托(闭包 块等等) 可以给方法传递一个代码块
比如
def transaction(tx as ITransactionable transactionalAction as ActionDelegate):
try:
transactionalAction()
tx Commit()
except:
tx Rollback()
raise
finally:
tx Dispse()
我们仍然可以使用这代码 正如我们前面所用的 transaction GetNewDatabaseTransaction() DoSomethingWithTheDatabase() 从语法上来看 是没有差别的 不过这两个版本还是有微小的差别 CLR确保了如果try程序块能够成功执行 就进入try程序块执行 这是using()语句正确执行的关键 其他的场景也是一样的 第一个版本可以利用这个能力 第二个版本不能 (原因是第二个版本是在运行时调用方法 而第一个版本只是替换事务代码块得到修改后的结果 ) 我们还可以利用Boo的元编程做些什么呢?相当多 关于这个内容可以写一本书(实际上我已经写了这方面的一本书 ) ) 作为一个简单的例子 而不一定是良好设计的的最好例子 你可以修改语言的if语句的语义 有一次我不得不这样做 我把if语句修改下面模式 if foo == null # do something为这个模式 if foo == null or foo isa NullObject # do something现在 当我们检查null的时候 我们也检查这个对象是否是NullObject的实例 NullObject是我的应用程序中的一个自定义类型 这使得在我的应用程序以一种自然的方式使用NullObject模式 val = NullObject() # set val to a new instance of NullObjectif val == null # will be piled as val == null or val isa NullObject print Value is null else print Value is not null 我们已经扩展了语言认为所有继承自NullObject的对象作为null 从长远来看 有能力去修改语言的基本组成部分是我的工作(和语言的使用)容易得多 在继续下一步之前来看最后一个例子 我想告诉你如何在Boo应用程序中使用不到 行代码添加一个(简单的) 契约式设计 (类不变式) 这是代码
[AttributeUsage(AttributeTargets Class)]class EnsureAttribute(AbstractAstAttribute):
expr as Expression def constructor(expr as Expression):
self expr = expr def
Apply(target as Node):
type as ClassDefinition = target for member in type Members:
method = member as Method continue if method is null
block = method Body
method Body = [|
block:
try:
$block
ensure:
assert $expr
|] Block
用法如下
[ensure(name is not null)]class Customer:
name as string def constructor(name as string):
self name = name def SetName(newName as string):
name = newName
现在任何把名字设置为null都将导致一个断言异常 这个技术相当强大和容易使用 我将前置条件的标记的实现留给读者 这个例子也示范了直接使用编译器的对象模型(AST)的强大 我们不局限于C++宏的文本替换 我们可以查询对象模型并以非常自然的方式修改它 那么现在我想你相信Boo是一个非常适合构建DSL的语言 我只是从表面上浏览了一下它的潜力 还有很多有待于你的探索 其他几项优势 Boo是静态编译类型的语言 这意味着你的DSL拥有标准CLR代码的所有优势(即时编译器 垃圾回收 调试等等) 从性能角度来看 你的应用程序代码和DSL代码没有任何区别 因此基于Boo的DSL对于经常需要修改和需要高性能的代码是理想的选择 在产品中不得不改变的这样的共同的需求往往推动人们使用基于XML的系统 规则引擎等 即使没有考虑完全 用XML编程 这样的辩论 这些选择都遭遇了低性能的问题
cha138/Article/program/net/201311/11679相关参考
在Web开发领域编程语言PHP优势在哪 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 在多数WE
知识大全 从文思海辉在语言服务领域的成就来看,海航科技集团怎样
从文思海辉在语言服务领域的成就来看,海航科技集团怎样?据有关资料显示,海航科技集团旗下的文思海辉此时开拓语言服务市场有很大的发展空间,发展状况应该也不错。从文思海辉通过CMMIDEVML5评估来看,海
恩格斯指出:每一时代的哲学作为分工的一个特定的领域,都具有由它的先驱传给它,而它便由此出发的特定思想材料作为前提,因此
恩格斯指出:每一时代的哲学作为分工的一个特定的领域,都具有由它的先驱传给它,而它便由此出发的特定思想材料作为前提,因此,经济上落后的国家在哲学上仍然能够演奏第一小提琴,这说明_____。A、社会意识是
NET介绍微软NET战略及技术体系NETFramework框架类库(FCL)公共语言运行时(CLR)通用类型系统(CTS)公共语言规范(CLS)程序集(Assembly)应用程序域(Applica
《会计信息化发展规划(2021—2025年)》提出,围绕注册会计师行业审计数据采集、审计报告电子化、行业管理服务数据、电子签章与证照等领域,构建注册会计师行业( ),发挥数据要素对注册会计师行业的创新
会计改革与发展十四五规划题目:《会计信息化发展规划(2021—2025年)》提出,围绕注册会计师行业审计数据采集、审计报告电子化、行业管理服务数据、电子签章与证照等领域,构建注册会计师行业(),发挥数
作者LucasJellemaOracleACE和Oracle融合中间件区域总监 通过一个简单的示例了解如何配置ESB以发布企业事件 年月发表 在面向服务的体系结构(SOA)领域一个比较重要的
能够拥有强大的搜索引擎是每个网站的心愿而一个强大的搜索引擎的制作又是相当复杂和困难的它涉及到效率准确性和速度等诸多方面这里介绍的搜索引擎不会涉及到这么深的研究只是针对特定的内容进行精确的查询一个功能复
专家谈SQLServer2005CLR 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 在SQLS
《中共中央国务院关于推进安全生产领域改革发展的意见》要求,坚持源头防范。严格安全生产市场准入,经济社会发展要以安全为前提,把安全生产贯穿城乡规划布局、设计、建设、管理和企业生产经营活动全过程。构建()
电力安全生产知识竞赛题:《中共中央国务院关于推进安全生产领域改革发展的意见》要求,坚持源头防范。严格安全生产市场准入,经济社会发展要以安全为前提,把安全生产贯穿城乡规划布局、设计、建设、管理和企业生产
《中共中央国务院关于推进安全生产领域改革发展的意见》要求,坚持源头防范。严格安全生产市场准入,经济社会发展要以安全为前提,把安全生产贯穿城乡规划布局、设计、建设、管理和企业生产经营活动全过程。构建()
电力安全生产知识竞赛题:《中共中央国务院关于推进安全生产领域改革发展的意见》要求,坚持源头防范。严格安全生产市场准入,经济社会发展要以安全为前提,把安全生产贯穿城乡规划布局、设计、建设、管理和企业生产