最近又读了一些进化论。联想到当前,最有潜力和最有影响力的几种计算机语言:C/C++,Java,.Net,D,当然其中.Net不是单一的语言,而是一个多语言的平台。其中D语言大家相对比较陌生。这里我要重点说的是C++和D。
先说C/C++。
虽然C++和C有很大的差异,但我还是要把他们放在一起,因为它们的很多共同的优缺点。先说优点:
C/C++历史悠久,有广泛的支持平台、的现有库、用户基础、性能就更不用说。但是它们有缺点,很致命,就是开发效率低。虽然使用现代C++在很大程度上改善了开发效率低下的问题。但是C++相比于C还有另外的缺点:
1. 学习难度高!以至于大家经常说,搞了5年C++,不敢说熟悉C++,更不敢妄谈精通了。对于有相当功底的C++开发人员,也经常出错。
2. 编译时间长。这主要归因于对C预处理器和语法的兼容,现代C++程序,一般都使用相当大量的模板,这使得编译时间不可接受。一个简单的spirit语法分析器,仅一个源文件,在2.4G双核至强4CPU的服务器上编译,超过一分钟。更不用说使用模板无法保密源码。
3. 当前(C++0x之前)的C++,对模板元编程的语法支持非常差,boost.mpl的那一套虽然解决了问题,但是相当丑陋。
这几个缺点在D语言中基本上不存在,主要是因为D语言是新设计的,并且它完全抛弃了C++:“对C尽最大可能兼容!”的设计思想。虽然它没有对C做最大可能的兼容,但是它仍然可以有效地与C进行合作,这在链接层次上完成,功能上有点类似于C++上的extern “C”。
需要思考的是,C++发展至今,经过了很多的演化,几乎在每一次重要的演化中,它新加的特性都得到了后来设计者都无法预料的发展和应用,最突出的就是,最近几年的模板元编程发挥出的巨大威力就是当初设计者完全没有预料到的。当第一份模板递归程序证明C++模板语言是一个图灵完备语言的时候,大家只是把它当作一个纯理论上的东西,从来没有想到它后来会在实际应用中有那么巨大的作用。就如同当初爱因斯坦发现时,没有预料到后来会有原子弹一样。
这里值得一提的是,为什么会出现这样的现象?复杂性理论告诉我们,当事物的复杂程度达到一定等级的时候,它的演化就会脱离它的设计者最初预订的目标。比如在生命诞生之初,在原生营养汤里面,有机分子终于因为某种原因随机合成了第一个有复制能力的复杂分子。在之后,一切的发展都显得那么自然而然。但是,这里有一个关键,就是在“那个东西”的复杂程度达到那个阈值之前,它的发展是非常缓慢的,甚至在达到那个阈值之前它就已经消亡了,实际上大多数情况都是这样,只有少数能越过那个门槛。
对于有生命的事物,越是有活力,越是复杂,它的变异点越多,它能产生的可能性空间就越大,从而有可能最终成功地越过门槛的概率就越高,当然它也必须有很大活力。这两点也许是相互依存的。
当然,这里的“有生命”,指的不是我们通常意义上说的生命,而是它的一个延伸。
看来,C++今日的成功,我们要归功于它的复杂。而不是单纯把它的失败归因于复杂。继续举boost.mpl的例子,因为当初C++模板的设计不是为了元编程,仅仅是为了更好地支持stl,更好地支持静态分派。因此,没有元编程中大概是最重要的一个功能:variadic template,这使得mpl.vector/mpl.map/bind/function/tuple等等的实现很难处理,需要写很多个仅仅是参数数目不同的偏特化版,这是个很繁琐无聊的工作。幸好,有人发明了boost.pp,使用最原始的C预处理来完成这个工作。结果当然是好的,boost.pp虽然比boost.mpl更丑陋,但是比起一遍遍地重复相同的代码要好得多。
从这里我们可以看到,冗余的,累赘的功能怎样发挥了它的能力。对C预处理语法的兼容一向被认为是C++最大的一个累赘,有很多人提出很多不同的惯例和方法来最大化避免使用C预处理语法,比如用inline代替带参数宏,用import(比如VC扩展允许import)代替include,用编译时常量代替宏常量等等。这些惯例和方法的确在某些方面解决了问题,规避了C++的缺陷。但是,假如C++98把预处理完全从语言中剔除,那么,在进行模板元编程时,就只能一遍又一遍地敲入重复代码,或者写出完全lisp式的代码如list<int,list<float,list<string,list<long> > > >,这比起list<int,float,string,long>如何?前者完全可以浇灭掉任何人对list的热情,而实现者要完成mpl.list,就只能重复一大堆一大堆的冗余代码,而这会浇灭实现者的热情。其结果就是,mpl仍然只停留在理论阶段,任何实际的需求都不会被发掘出来。template meta programming也只停留在理论阶段,我们现在使用template也仍然停留在“不同类对象的容器”阶段。
现在说D语言,它基本上是一个“大杂烩”式的语言,几乎所有主流语言的功能,它都实现了。它放弃了对C的语法级兼容,但是它仍然不抛弃“native code”这个设计思想,原则上它的所有语法和语义只为生成本机代码而优化。就是说,它的语法不是“为虚拟机代码而优化”,当然,理论上也可以生成虚拟机代码,但很难优化。也就是说,D语言在本质上只是一个“更好的C++”,最多,只是比“目前的C++”更好。它比C++简单,但同时也失去了C++复杂性中的变异性可能,它只能在C/C++的这个进化方向上更好。如果它想要更广泛的应用,就需要有更多变异点,在基本的设计原则上,不能和C/C++的重合太多,以防止变异的可能性空间被限制。
现在说Java/.Net,它们在本质上比较相像,都是为虚拟机而优化。而一旦有了虚拟机这个中间层,很多为本机执行而优化的可能性就失去了。我们可能在高层使用更广泛的指令集,而虚拟机这个中间层的指令集是固定的,它无法识别更高层指令集的优化。比如,我们为了优化视频解码程序,在C/C++中可以使用intrinsic,或者buildin function,它们把函数调用直接映射到CPU指令,这样,不使用汇编语言就可以使用如MMX/SSE/SSE2/3DNow等增强的指令集。而使用虚拟机,怎样实现?那就只能增加虚拟机的指令集。
是更简化,还是更复杂?我觉得应该是更简化。
网络速度变得越来越快,终究有一天,会光纤入户,最终,或许用不了多久,网络速度已经比我们的硬盘快了。
目前的PC(个人电脑)之所以是现在这个样子,是因为我们的硬盘,相对于网络有两个优势,一个是速度,一个是隐私。当速度已经不是问题,就只剩一个隐私了。而隐私问题实际上只是一个心理问题,人们总觉得把隐私敏感的东西也存储到网上 不安全,容易泄露,而实际上,保存在自己的硬盘上并不比存在网络上更安全,更不容易泄露。如果大家都认识到这个问题,那么,硬盘,对于PC,就已经不重要了。(——除非此时硬盘已被如Flash一类的新产品代替了,并且速度比网络至少快一个数量级,并且大家有那么高的吞吐量需求。)
应该不会太久,我们设想这时的网络速度是50MB/s,那么pc,只需要内存和cpu,操作系统都不需要了,就像现在的电视,一打开就可以用,并且所有的东西都是最新的(根本不需要什么软件更新一类的东西)。仅仅需要的就如同现在和很久以前的旧时代里从终端登录:用户名,密码。不同的是,那时是consol终端,现在是比Vista更强劲的终端。
pc 的cpu也更快,内存也更大了,而同时,网络分布式计算的增长更快。很多计算根本都不需要pc的参与,他只需要向网络发出命令,比如编辑文档,收发邮件,游戏(图象计算密集的除外,现在的网游服务器可以认为是未来全分布式游戏时代的雏形)。
浏览器也泛化了,进入计算机所有的操作都是在“浏览器”中进行,就像我们现在在在图形界面或consol终端进行操作一样。我们个性化的东西就是自己的配置,配置哪些东西是我一步(我的顶级目录)操作就可以得到,那些东西需要两步(二级目录),那些需要三步,……整个世界上所有的东西我们都可以得到,只是得到它的方便程度不同。
这个终极的理想在过去和现在已经有一些雏形,如一些网吧里的机器,一些学校的机房,有windows的,有linux的。现在ubuntu已经在朝这个方向努力了。如果linux最终能在这个方向上走到windows前面,或许微软的日子就到头了,除非他也顺应时代潮流。