- 论坛徽章:
- 5
|
回复 40# lcqtdwj
lisp复杂程度一点都不高。我一句话就能解释明白,所谓“lisp复杂程度高”是因为lisp太灵活,你想做啥就做啥,而对于你想做的,有各种各样已经规定好的实现(包括if和lambda),而这些东西太多了,你才会觉得复杂。
lisp的本质,一句话就能说明白:程序是以S-exp表示的广义表,对程序的求值(运算、执行),本质上是对广义表的求值,这是一个递归过程:对广义表的第一个元素求值,并决定如何对其他元素进行求值。完了。
比如(display (if (< a 1) 'a 'b)),先求值(display ...),首先根据描述对display求值:他是个函数,那么函数的求值方式是对其所有后继子项求值,那么开始对(if ...)求值,if是个special-form,他的求值方式是对第二项进行求值,如果是真就对第三项进行求值,否则就对第四项进行求值………………
这个过程说起来复杂,实际上就是一个多叉树的遍历而已,任何语言都可以很简单地做到(所以说ruby能简单实现scheme真不是什么很自豪的事情),只是lisp特别灵活,它通过第一个元素对这个遍历过程进行了控制。你可以认为lisp特别适合于dfs搜索功能,当然这就是“lisp适合人工智能”这种论断的原因。
那lisp的问题在哪儿呢?在于效率。如上所说,要根据定义去执行lisp程序出乎人意料的简单,问题是性能就不好说了。ruby本来就慢,用这种方式求值lisp没什么问题,但是如果你是正儿八经去考虑高效地执行lisp程序,你不得不考虑很多问题:lisp到字节码甚至机器码的翻译(为了jit或者效率)、cons的高效存储、轻量级编译器的实现、垃圾回收的效率等等等等,这才是lisp的难点所在,为了克服这些难点,实现要么减少了lisp的灵活性(不允许修改+-*/神码的),要么体积会很大(以同时支持灵活性和效率),这才是lisp不容易实用的原因。
但是你必须承认,真正做到了这点的lisp效率是ruby的300多倍(参看programming language benchmark game),而做不到这点的lisp(如用ruby实现的lisp)本质上就是个toy而已。
最后说说ruby吧。这是我第一门脚本语言。最开始对它是很有好感的,但是因为了解到它是perl的后继,我就开始学习perl,感觉perl太难学就转了python,后来我常用perl(工作中)和python(私下里),就对ruby生疏了。作为一门perl的后继语言,ruby无疑是目标明确的——它拉低了编程的门槛(至于这个目标是不是有益去问OwnWaterloo吧),然而ruby自身也有很多问题,第一个就是翻译的问题了,第二个就是效率问题。ruby的效率低一方面用的是yacc而不是自行实现的翻译器,另一方面它的执行方式和朴素的lisp非常像——它也是执行语法树的!而且是以一种写死的遍历方式进行执行,这种方式我看是扬短避长了。它没得到lisp的灵活性,反而损失了性能,这是得不偿失的。
由此可以看出ruby对真正元编程的支持了,目前是很弱的,然而应该有足够的潜力达到很好的支持水平。而这本书里面提到的“元编程”,我觉得实在是不能被称为元编程——这种元编程不是通过生成代码来实现的,对效率没有任何额外的好处,只是“运行时获取程序所有信息”而已,最多算是“元执行”或者“元计算”。所谓元编程,即“生成程序的程序”,最初是为了可维护性(如检查)和效率(如直接生成复杂代码的执行结果),而这些在单趟的ruby模型下是做不到的,除非你用ruby去生成ruby代码:用ruby写DSL来描述需求、DSL产生数据结构、数据结构再产生ruby代码,再执行产生的ruby代码。如果是这样那还有点看头,不过ruby做到这个也就平淡无奇了,看看lua的一个绑定库的DSL吧:
- require 'lbind'.export(_ENV)
- require 'lbind.types'.export(_ENV)
- module 'gd' {
- export = true,
- include "gd.h";
- subfiles {
- --"gdImage.bind.lua";
- };
- object "gdImage" {
- method "new" :cname "gdImageCreate"
- (int "sx", int "sy") :rets(selfType:ptr());
- method "newTrueColor" :cname "gdImageCreateTrueColor"
- (int "sx", int "sy") :rets(selfType:ptr());
- method "delete" () :alias "close" :cname "gdImageDestroy";
- method "color_allocate" :cname "gdImageColorAllocate"
- (int "r", int "g", int "b");
- method "line" :cname "gdImageLine"
- (int "x1", int "y1", int "x2", int "y2", int "color");
- include "errno.h";
- include "string.h";
- method "toPNG" (char:const():ptr "name") :body [[
- FILE *pngout = fopen(name, "wb");
- if (pngout == NULL) {
- lua_pushnil(L);
- lua_pushstring(L, strerror(errno));
- return 2;
- }
- gdImagePng(self, pngout);
- fclose(pngout);
- lua_pushboolean(L, 1);
- return 1;
- ]];
- };
- };
复制代码 ruby能产生这么紧凑自然的DSL么? |
|