2012已经过去,2013刚刚开始。想起擦肩而过的末日,不禁胆寒,认认真真地补上一篇总结吧!今晚,凭悼我祸祸过的光阴!从明天起,做一个幸福的人!看书,编程,宅在家里。

引子

1865年1月31日,美国众议院,国会最激进的共和党人撒迪厄斯·史蒂文斯沉吟半晌,环视挤满了人群的会议厅,终于回应了纽约众议院代表的质询,“修正案的真正目的,只是为了法律面前人人平等”。而他此前一直在宣称人人生而平等,黑人和白人平等。为了使第十三修正案顺利通过,为了最终废除奴隶制,他在人人生而平等前加上了“法律面前”几个字,避开了争论最激烈的种族平等问题。听着楼下的辩论,楼上的林肯夫人说:“这个老家伙居然憋了这么久,他将来会成为一个政治家的。”

投票结束后,在走廊里,艾萨质疑他丧失了自己的良心,居然否认自己为之奋斗三十年的“人人生而平等”,否认黑人的权利。面对非难和质疑,史蒂文斯说出了下面这段话:“我希望修正案能通过......为了这份修正案,为了我奋斗毕生的事业,为了那些在抗争道路上献身的黑人,为了千千万万牺牲的士兵,没有什么是我不敢说的,也没有什么是我不能说的。”

这是 史蒂文·斯皮尔伯格 2012年的新电影 林肯 里面的一段场景。

选择什么语言,完全是由目的决定的,这才是语言的奥秘。真正掌握语言奥秘的,不是作家,不是相声演员,而是政治家!好吧,也有可能是编剧。

我生命中的那些编程语言

我接触的第一门编程语言是ANSI C,谭浩强教授的《C程序设计》卖了1000万册,里面有我一本。可除了作业,我只用它做过一个程序。那是一个月黑风高的晚上,宿舍里的兄弟们都已酣然入梦。我折腾了大半夜,用Turbo C在那台486上一条线一条线地画了一个窗口,鼠标在窗口内一点击,就会以点击的坐标为圆心画一个圆。编译运行成功后,我对着屏幕难抑内心的激动,呵呵傻笑起来。现在想起来,觉得当年自己真是傻得很有道理。

多年以后我才知道,C语言是由UNIX的研制者丹尼斯·里奇(Dennis Ritchie)于1970年在由肯·汤普逊(Ken Thompson)发明的B语言的基础上发展和完善起来的。除了知道它比我还老,有什么意义?

学汇编是在C之后还是之前,我已经不太记得了。能记住的只有寄存器和MOVGOTO等有限的几个指令了,当然还有代码的长度。在应用程序这种级别的开发中,恐怕除了破解,再也找不到汇编的身影了吧。

之后我接触到了Java 1.2,也是我一直使用到现在的语言。当时为了从面向过程的思考方式转变成面向对象的思考方式也经常跟自己较劲。为了理解多态性、封装性和可继承性耗费了很多脑细胞,还经常搞不清楚什么是重载(Overload),什么是重写(Orverride,当年一般叫覆盖)。但Java当时于我,不过是一门选修课而已,和她再次相遇,是在多年以后。

在大三那年的暑假,我边学边练,用Visual FoxPro给一家电器店做了一套简易的进销存系统。最后系统交付时,看着我演示的功能,老板提出了一个让我觉得匪夷所思的问题。他问,你这个报表的线能不能细一点,或者干脆不用线?我懵了,他很和善地跟我解释:“线粗费墨,墨盒也不便宜啊!”那是我第一次用专业技能做一个实用的东西,但至于后来这东西有没有用起来,我不得而知。并且以后再也没用FoxPro做过任何东西。哦,说到语言,它应该可以归为SQL吧。咦,我当时写过SQL吗?这个真不记得了。

既然聊编程语言的时候可以说SQL,HTML应该也可以出场吧。那时候互联网刚刚兴起,Netscape正如日中天,ICQ还在国门外徘徊,OICQ也没出父胎,在校园里流传的只有WPS的金山传说。我能遇见HTML,在当时也算很时代前沿吧。虽然我征服了DHTML,可惜却被CGI(Common Gateway Interface)这个美其名曰普通门的门拦在门外,没能鼓捣出个网站来。不然,也许,大概,差不多,能更早认清自己是块废柴的现实吧 :(

javascript是我的最爱之一,我是在毕设的时候遇到它的,不过不是用它编程,而是要做个它的编译器。当然,也不是完整意义上的编译器,只是为了提取javascript代码中会显示出来的字符串。找到alert不难,难得是找到各种字符串用机器翻译出来。还好有Lex和YACC这样的神器,最后,我毕设居然通过了!

工作后的第一个项目就是用JavaScript做的Web应用,前后端都是,前几天在微博上,一前端工程师慨叹掌握一门服务端编程语言是多么重要,求推荐再次成功引发了一场口水战。我不仅跟着慨叹,大概没几个人记得Netscape的Serverside JavaScript了吧,古今将相今何在,荒冢一堆草没了.....

我再次遇到Java是在它的1.5之后,算是没遭过EJB的罪,直接跟进了Struts,所以我不恨她。之后又陆续用过Springframework,iBatis,Hibernate。啃了一段时间MyFace之后,还折腾过几天wicket。用seam做了个项目后,又尝试了sitebricks,最后因为Guice年纪大,bug比weld少而向sitebricks倾斜了很多。可外面又传来了Scala的喊杀声,扬言要灭了自己的老子Java,跟当年Java灭了C一样让历史重演,所以我又看上了playframework...

这些年虽然一直以Java为主,但其间也试过Zope,用PHP搭过公司网站,用ActionScript写过小游戏,都是玩票的性质,没有深入,也缺乏半夜画线攒窗口的热情了。

转眼Java已经7了,Sun也步BEA的后尘归了Oracle。想想这些年我经历过的这些女人,咳咳,语言!以后请不要把编程语言比成女人,这不公平,谢谢!想想这些年我经历过的这些语言,不免唏嘘。这笔流水账就像一个懵懂的人走进了一片大森林,漫无目的,全凭际遇。但其实冥冥中自有天意,这些语言之所以能来到这个世界并挣得一席之地,是由自然规律支配的(身后大厂的撑腰不容小觑,想想delphi和.net吧),它们都是语言生态系统中的一份子。

语言生态学

Java是运行时编译、静态类型的指令式语言。什么意思?

编程语言也有很多种不同的风味1。或者说不同语言里会有不同编程风格的烙印。弄明白这些差异很关键,也很有趣。

1咦,我为什么要说也?

注意 下面的提到的分类方法只作为对语言多样性思考的辅助。虽然有些分法更容易形成清晰的分类,但没有完美的分类方案。

现在语言也会打破各种界限添加新特性。也就是说我们最好只说某种语言比其它语言“函数化程度更低”,而不要冒险说这种语言是函数式语言,而那种语言是指令式语言。

但我们毕竟不是政客,说话不用那么滴水不漏,所以还是干脆点,讨论下“解释型与编译性”,“动态类型与静态类型”,“指令式与函数式”语言之间差异。是的,我没提”面向过程与面向对象“。

不同的语言可能会有不同的侧重;比如动态类型的语言可能更看重部署速度。而Java则更强调安全性、代码清晰程度和性能,并愿意接受代码的繁琐性,愿意放弃一定的灵活性(比如部署时)。

解释型 vs. 编译型语言

解释型语言是那种源码中的每一步是什么就执行什么的语言,不会在执行开始之前把整个程序转成机器码。编译型语言和它相反,用编译器把人类可读的源码变成二进制形态被当做初始任务。

这种划分最近变得模糊了。在80年代和90年代早期,边界还相当清晰:C/C++及类似的语言是编译型的,Perl和Python是解释型语言。但Java同时兼具编译型和解释型两种语言的特性。字节码的出现把这个问题进一步搅浑了。人类肯定读不了字节码,但它也不是真正的机器码。

动态类型 vs.静态类型

动态类型语言关注变量包含哪类值(比如数字或字符串)的信息,而静态类型语言关注变量的类型信息。

静态类型非常适合编译型语言,因为所有类型信息都在变量上,而不在于变量的值。所以在编译时就可以推导出潜在的类型系统违规行为。

动态类型语言把类型信息放在变量所持有的值上,变量在不同的时间可能会有不同的类型。因此很难发现类型违规行为,因为变量的值要到运行时才能得到。Javascript就是最著名的动态类型语言。

指令式vs.函数式语言

指令式语言把程序的运行状态建模为可修改数据,通过一系列指令来改变程序的运行状态。因此,程序状态才是指令式语言中的主角。

指令式语言主要分为两类。一种是过程语言,比如BASIC和FORTRAN,把代码和数据完全分开,并且有个简单的代码操作数据范式。另外一种是面向对象(OO)语言,数据和代码(以方法的形态)被放在一起封在对象里。

函数式语言的观点与指令式语言不同,它把计算本身当做最重要的概念。函数式语言也会像过程语言一样对数据进行操作,但它不会修改输入的数据,而是像数学函数一样返回新数据。

至于我经历过的那些语言该如何归位,我想还是再等等吧。虽然它们最初都有自己的定位,可毕竟它们还在推出各自的X版,与之配套的框架、最佳实现、工具、制成品还在不断丰富。Java 8都要支持lambda了,保不齐Lisp清心寡欲了这么多年后也会搞对象。你能看清楚那个一口京腔骂“电梯里有俩2B”是个姑娘还是个人妖吗?反正我是没看出来。

语言金字塔

其实除了前面那种技术特性上的分类,语言还可以根据目的分层。下面这幅图就是编程语言的金字塔:

编程语言金字塔

图 1.编程语言金字塔

对于这三层的解释,请看下表:

表 1.编程语言金字塔

名称 描述 例子
特定领域层特定领域语言。与应用领域的特定部分结合非常紧密。Apache Camel DSL, Drools,Web模板
动态层开发速度快,生产率高,功能灵活部署Groovy, Jython, Clojure
稳定层核心功能,稳定,经过良好测试,性能高Java, Scala

果然是花花公子的慧眼,让你看出来了,上面的例子确实基本都是Java他们家的。

开篇说过了,语言的奥秘在于为达成目的巧妙安排,并无优劣之分。所以请你不要浪费时间跟人打口水仗,也没必要求推荐让别人打口水仗。先搞清楚自己的目的吧,毕竟此生有涯,扯皮无边。至于该如何选择,如何取舍,那要靠自己花时间去琢磨了。