为脚本语言平反-JavaScript篇(2)
一、QoBean的元编程框架
===========
现在开讲“DSL in JavaScript,with QoBean’s meta programming framework”。先说说QoBean的元编程框架。这是一个仅仅100来行的小小框架,里面有几个关键函数是我们在讲DSL时要用到的:
Weave(where, code):表示对于一个函数f,在指定where的位置,替换成代码code。如果where是正则表达式,则code中可以使用获取匹配;如果where是字符串,则表明将第一个查找到的该字符串替换成code。
Block(func, tag):对函数func(或直接是它的代码文本)进行结构分析。tag标志为['body', 'param', 'name']之一时,返回该函数源代码相应位置的一个字符串;tag标志为’scope’时,返回一个字符串str,用eval(str)可以在当前位置生成一个新的、具有该代码上下文位置上的闭包的函数;tag标志为’anonymous’时,直接返回一个函数,但该函数是全局函数。对于tag是['scope','anonymous']之一的情况,所得到的新函数是传入参数func的一个完全相同的副本,只是新函数所在的闭包位置不同。
Unique(obj):生成obj对象的一个唯一化的实例。新实例obj2具有原obj对象的全部属性,但修改新对象obj2的成员时,不会影响到原obj对象。这个过程,与Block(func, tag)调用时,tag为['scope','anonymous']之一的情况有类似之处:都是生成一个新的复制,不同的是Block针对函数,Unique针对对象。
Scope(obj, func):使函数func(或直接是它的代码文本)执行在obj的对象闭包中。当func执行在obj的闭包中之后,func所访问到的变量名,即是obj的属性;func访问到的函数名,即是obj的方法。
Owner(obj, func):使函数func(或直接是它的代码文本)执行在以obj为this对象的环境中。在JS中,当一个函数执行时,this关键字要么指向全局的window对象(func是普通函数);要么指向方法所属的对象实例(func是对象方法)。Owner()函数用于改变这种关系,使得函数func在执行时,this关键字总是指向obj。――一般来说,这个功能在其它的JS框架中被实现为Function.prototype.bind()。
QoBean的元编程系统中还有一些其它的函数,但对于我们讲DSL不关键,所以先不讨论。除了上述讨论的函数之外,我们在DSL部分不会用到其它的任何函数,也不会用到某种JavaScript引擎的独特功能――甚至不会用到arguments.caller。所以,我们在这里实现的DSL,可以跑在ECMS Script标准中的任何一个JavaScript引擎之中。
最后综述一下上面的五个函数。他们其实对于Meta Programming有着特殊的含义。
Block(),其实是一个简单的Parser。他能够快速分析一个代码文本块,以使重新组织它。相当于我们在书写代码时的重构、改写。
Unique()与Scope()是功能近似的函数,只是一个作用于函数,一个作用于对象。作用是得到一个复制,相当于我们书写代码时的ctrl + C操作。
Scope()与Owner()也是功能近似的函数,前者用于改变代码的上下文,相当于书写代码时移动一段代码(例如把局部函数变成全局公共的),有点类似于ctrl+V操作;后者用于改变代码(作为对象方法时)的属主,相当于基类中的方法,或重构,或范型等等。
我们注意到,上面几个函数,事实上模拟了我们书写代码时的很多行为。在前面讲到过的文章中,我说到过“那么QoBean如何定义‘元语言’呢?QoBean对此有两项解释”:
- 元语言定义程序(program)的基础元素:算法与数据结构
- 元语言说明编程(programming)的基本方法:代码的组织形式
这里的五个函数,就是第二项解释中的“编程(书写程序)的基本方法”的抽象、实现。
二、DSL的基本设计
===========
现在我们来考虑一个“通用DSL”应该是什么样子,也就是如何设计它的问题。首先,它是一种语言――这很废话对吧?哈哈。其实不是,这是一个语言,表明它应该有语法、语义、语用的问题。语法就意味着需要一个解析器(parser);语义就意味着对于语言中的关键字要有功能实现,即要有执行器(evaluator);语用,就意味着说相同的话――相同的代码文本,在不同的环境下效果未必一致,所以也就意味着要有环境(environment)设定,亦即是“上下文相关文法”或“上下文无关文法”的问题。
这三个方面的问题有点令人挠头,但用个类比,就挺简单的。例如说“吃饭了吗”这句话,首先就包括汉语语法的问题,例如省略主语、疑问句和主谓结构等等。所以,我们可以改变一种新语法来陈述它,例如“饭,吃了吗”,或“吃了吗,饭”。这些,只是语法上的变化。说话的、写程序的人,先约定一种规则,然后按这个规则来理解它,就行了。
那么语用呢?或者说所谓的“上下文相关/无关”是什么意思呢?同样的,上面这句话,如果是早晨我跟你碰面在公司楼下,我问这句话的意义,跟说“Hello”,或者“今天天气不错”其实差不多,只是个问候语。但如果是朱
建议继续学习:
- 构建前端 DSL (阅读:2703)
- 基于DSL风格的代码重构 (阅读:2164)
- API设计新思维:用流畅接口构造内部DSL (阅读:2135)
- 为脚本语言平反-JavaScript篇(3) (阅读:1837)
- 从Java和JavaScript来学习Haskell和Groovy(DSL) (阅读:981)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:aimingoo 来源: aimingoo的专栏
- 标签: DSL QoBean
- 发布时间:2009-10-23 23:53:32
- [54] IOS安全–浅谈关于IOS加固的几种方法
- [52] android 开发入门
- [52] 如何拿下简短的域名
- [51] 图书馆的世界纪录
- [49] Go Reflect 性能
- [49] Oracle MTS模式下 进程地址与会话信
- [47] 【社会化设计】自我(self)部分――欢迎区
- [46] 读书笔记-壹百度:百度十年千倍的29条法则
- [36] 程序员技术练级攻略
- [29] 视觉调整-设计师 vs. 逻辑