我的程序语言实践
动静之间,不变的本质——我的程序语言实践
===========
引子
====
源于SD2.0大会的召开,以及拙作《JavaScript语言精髓与编程实践》一书的出版在即,CSDN、博文视点以及《程序员》的编辑都希望我写一点关于语言的东西。我已经为这个问题苦恼了很久,因为我不知道可以说什么,既可以与先行者有别,又可以使后来者为鉴。
这下便借用《程序设计语言实践》一书的书名,讲讲我的经历吧。
从动态语言到静态语言
====
我所学的第一门语言其实是数据库编程语言DBASE,参加的是学校的一个暑期的关于微机操作的培训——程序设计语言只是其中很小的一部分,我们得从键盘键位之类的开始学起。就这样,我也只学了十天。这是在1994年,当时用的是DBASE III。DBASE是解释执行的、弱类型的一种语言,我用它写过数据库的前置的口令检测程序。很快我就换成了BASIC,换这门语言的原因是当时要参加省赛区的一个竞赛,我用了一个月略多的时间来学习它就参赛了,结果是第二名。在后来的学习中,我用BASIC写过内存处理、端口处理程序。到了1997年的时候,我的一个朋友的毕业设计要用BASIC来写,当时我已经丢下BASIC两年了,但还是用了一晚的时间完成了一个考试管理系统,包括班级、学科管理、成绩管理和档案管理(含磁盘检测以上报档案)。当时我用了一个名为Turbo Basic的东东,是Borland做的最后一款BASIC语言的工具,据内幕说是因为与微软存在协议,后来Borland再也没出过这一语言的工具。
(*) 顺便补充一点,那个微机培训的课程是一个月,而我当时对文学感兴趣,因为要去北京参加一个笔会而只学了十天。我对文学的兴趣持续到1999年,在2000年的时候,一篇早期的文学作品拿了网易首届网络文学大届的散文金奖(这个大赛也只办了一届,哈哈)。而对文字的喜好则持续到现在,成了我写书作文的根基与动力。
在DOS时代还有一种可编程的批处理(当然现在在Windows系统中也有,只是用的人实在不多了),我曾经用它与BASIC和汇编结合起来,写过系统加锁程序。这些大概都是在1996年之前的事了。
我学习编译型语言的时间晚于解释型的,最初是在1995年初开始自学《数据结构》一书,那一版的书就是用PASCAL语法来讲的,而我学算法语言晚于学《数据结构》,所以当时并不会PASCAL,也不可能在当时的BASIC中理解这些复杂的数据结构。因此我又买来Pascal语言入门教材自学,然而题不对板,数据结构中用的与我这本书所讲的,以及我能用的Pascal编译器三者全不靠谱,而那时候我还在死学死用的层次上,学了半年而无有小成。
然而《数据结构》却没有耽搁,对这门学科的学习成了我这么多年来理解编程的基础。再后来,我又开始自学汇编语言、算法语言(Pascal)和操作系统原理,到了1996年初,我基本上已经完成了对语言和系统的自学。这个时候,我的语言选择已经从Basic转到了Pascal。
换言之,我从动态语言走到了静态语言。不过这样说,我可能被立即反问:它们是动态语言吗?我慎之又慎的思考之后的回答,仍然“是”。前面提到的DBASE、BASIC和批处理其实都有动态语言的特征——尽管这在我学习它们时是不知的。
回归动态-从Delphi到JavaScript
====
知道我的朋友很多是因为Delphi以及我所写的《Delphi源代码分析》一书。我从1996年开始做一些商业产品的代码,一直到2003年都是使用的Pascal/Delphi系列语言,以及一些汇编语言。我从传统过程式开发转变到面向对象开发,用了非常长的时间——超过两年。直到2003年的早些时候,我终于停下忙忙碌碌的、无止尽的代码书写,问了自己一个问题:Delphi是怎么回事?
为了给自己解答这个问题,我辞掉所有的工作,静下心来研究这门语言。准确地说,是研究静态语言的语法、语义以及面向操作系统的编译与二进制文件生成。《Delphi源代码分析》这本书讲的就样的一些内容:语言的基本要素、操作系统对语言的要求、语言的实现等等。只不过我是通过对Delphi的源代码的分析来展现这些罢了。
用了一年的时间,我终于看明白语言在“结构”方面的真相:所有的语言效果、语法以及二进制的执行能力,原来不过是操作系统理解的一堆“可执行和可存取的数据结构”。“编译”这一过程,无非是把这些细节隐藏起来,让程序员以为自己在写一种非常高级的、逻辑的、有趣的代码,而忽视掉背后的本质部分:静态的数据与指令。
如同我此前对于Pascal/Delphi的盲目一样,我学用JavaScript之初也是盲目的。我选择JavaScript的唯一原因,只是因为我在Web上开发时找不到第二种可以通用的语言(如果当时我能选择一种类pascal语法的语言,我一定会错失学习JavaScript的良机)。
我从1998年开始使用JavaScript,这离这门语言被创生出来不过三年时间——以语言的历史而言,这算得上是“追新”了。在最初我无非是把它当成一种脚本化的过程式语言,以及用来响应网页里的OnXXXX事件的一些代码。但在一两年之后,在我深受Delphi中的面向对象编程思想的影响之后,我发现JavaScript令我不堪忍受:它毕竟不是一门具有完整的对象特性的语言。于是我开始试图实现JSOOP:JavaScript的面向对象编程。
这一设想以及一些实践开始于2002年,但直到2004年初我才真正着手实施这个计划,到了2005年末这个项目延伸为现在的Qomo(Qomolangma OpenProject)。而我另一方面的计划——自2005年初开始写的一本名为《B端开发》的书,也终于因为Qomo项目而被放弃,变成了《JavaScript语言精髓与编程实践》。因为在Qomo开发过程中,我发现讨论JavaScript这种语言本身,远比“在浏览器端(B端)开发”更为有趣。尽管,在这其间我还用过PHP、Java与C#等等,不过相对于后面要讨论的内容来说,这些已经不重要了。
因为我对编程的理解,终于从Delphi走回JavaScript,从静态回归到动态。
JavaScript语言的基本特性
====
到底JavaScript是怎样的、以及为什么会吸引我呢?如今我之视见,JavaScript语言包括了四个方面的语言特性:过程式语言、面向对象语言、函数式语言和动态语言。具有过程式特性,是它入门容易的原因;面向对象特性则使它符合主流的程序设计思想;函数式是JavaScript语言的根基,而动态语言则是它的外在表现,以及强大到难于驾驭的根源。
前些时候在北京参与CSDN大会时,与一个老朋友谈到JavaScript,他说:JavaScript具有几乎所有主要语言形式的原子要素。我觉得,这个“语言原子”的概念就提得很好。的确,JavaScript在上述四个方面都表现平平,但每个方面都抓住了相应语言范型的精髓。不但如此,JavaScript还使用了一个最简而又最合理的方式来组织各种语言特性。仅以“动态”而论,《JavaScript语言精髓与编程实践》讲述了JavaScript所包括的四个方面的动态性质:
- 动态执行
- 动态类型
- 重写
- 实现动态环境的基础数据结构
源于本文篇幅,对于更深层面的问题便不讨论了,这里仅讨论一下静态执行与动态执行的某些本质上的差异。举个例子来说,下面的代码:
------
obj.aMethod(x,y,z);
------
这显然是一个对象方法调用。但对象方法是如何实现的呢?在静态语言中,因为有编译过程,所以我们把一个结构放在内存里,并使得它
- 拥有一个对象实例指针指向obj,
- 拥有一个对象方法指针指向aMethod()在代码区的地址,
- 在有效代码的前后加入处理x,y,z这些参数的代码(例如入栈与清栈)。
在执行时,我们将obj与aMethod交给执行系统,并传入指定参数(的序列),然后就可以按照既已编译的规则来执行了。
然而在JavaScript中,由于它是一个动态语言,因此编译的结果只是一个表达执行过程的语法树。这个语法树被存储为一个二叉树形式的数据结构。更细节的说,二叉树的Root/Left/Right三个节点分别表示运算符、运算元1、运算元2。以较为复杂的三元运算符“?:”来说,下面表达式:
------
isTrue ? expr1 : expr2
------
就被表达为
root(?)
/ \
left(isTrue) right(:)
/ \
left(expr1) right(expr2)
页:
[1]