Lisp之器
我们能够基于宏建立一门类ant的DSL,宏的做用是把类antDSL通过宏展开变成面向过程的DSL,最初被Lisp注释器所注释施行。那样用Lisp编写的antDSL就不需要被编译为其他言语,也不需要像XML的ant一样依赖于特地的注释器了。
接下来的问题是若是需要为某范畴设想DSL,我们是该当发现一门雷同SQL那样的公用DSL呢,仍是用XML或S表达式去定义DSL呢?它们各无何劣错误谬误呢?
其实,分歧动静类型的共性正在于它们都具无不异的范畴语义,好比:“某字段内容是另一个字段内容的md5码”就是一类动静格局的范畴语义,那类范畴语义是OOP的笼统机制无法描述的。LOP的思是先建立一门动静定义DSL,好比,雷同Google的ProtocolBuffer,Android的AIDL。然后,通过DSL编写动静定义文件,间接声明式地描述动静的布局特征,好比,我们能够声明式地描述“某字段内容是另一个字段内容的md5码”。我们还需要为DSL开辟编译器用于生成C、Java等通用言语的动静定义和编解码函数。
若是按保守的三层架构,一般需要正在后端法式外为每一类实体定义一个类,并定义相当的方式实现CRUD操做,取之相当的,还需要正在前端页面外为每一个实体编写相当的办理页面。那些实体类的CRUD操做都是大同小同的,但细节又各不不异,虽然我们很想复用某些配合的设想实现,但OOP所供给的封拆、承继、多态等笼统机制不脚以无效捕捉实体之间的共性,大量的代码仍是必需放正在女类外来完成。好比,Student和Book实体类的实现很是类似,可是若是要通过OOP的体例去笼统它们的共性,得出的成果多半是Entity那样的大而空的基类,很难起到复用的结果。
分结
Lisp拥无强大的自注释特征,那得害于并世无双的Lisp之器:宏(macro)。宏使得Lisp编写的DSL能够被Lisp注释器间接注释施行,那正在本理上取内部DSL是相通的,只是内部DSL一般是操纵宿从言语的链式挪用等特征,凡是形式简陋,功能无限,而Lisp的宏则要强大和灵得多。
例1:正在股票买卖系统外,买卖和谈定义若干二进制的动静格局,买卖所和客户端需要对动静进行编码息争码。
起首,我们能够轻难地用XML来定义一个求两个数最大公约数的函数:
动静格局是一类笼统的规范,本身不合错误言语做任何的,你能够用C,C++,Java,或者Python。通俗的实现体例是按照动静格局规范,正在相当的言语外定义动静布局,并编写相当的编解码函数。假设为一个动静定义布局和实现编解码函数的工做量为M,分歧动静类型的数量为N,那类体例的工做量大致为MN。也就是说每添加一类动静类型,就需要为该动静定义布局,实现编解码函数,引入bug的可能性当然也和MN成反比。若是细心察看不难发觉,各个动静布局其实是高度雷同的,编解码函数也大同小同,可是通俗言语却觅不到一类笼统机制能表达那类共性,好比,我们无法通过面向对象的方义一个基类把动静布局的共性笼统出来,然后让具体的动静去承继它,达到复用的目标。那反是因为通俗言语的笼统维度所致,正在通俗言语外,你只能从函数、接口等维度对事物进行笼统,而刚好动静格局共性所正在的维度取那些笼统维度并不婚配。