现在的位置: 首页 > 综合 > 正文

1990-1995年间学习编程语言的回忆录

2013年10月19日 ⁄ 综合 ⁄ 共 7630字 ⁄ 字号 评论关闭

(此处为人肉维护的镜像,原文请见:http://csbabel.wordpress.com/
 
翻墙请用Google Reader查看:http://csbabel.wordpress.com/feed/

 

 

绝对必要、又臭又长的作者声明:
1、虽然是回忆录,但本人是码农不是艺妓,想来看艳情的可以洗洗睡了。(推荐你看《往事回忆录》,那个很艳情,而且不黄不暴力)
2、我不是成功人士,想看成功人士的奋斗经历来励志的,可以关窗口了。(推荐你看《小兵传奇》,那个很成功、很励志)
3、我没开发过大项目,想看内核技术和巨型软件构建经验的,可以打酱油了。(推荐你看最近出的写WinNT故事的那本翻译书,不过我还没看过,只是听说不错)
4、我没有高学历,想围观高学历的地球原住民的,可以飞过、飘过、走过、路过、虫洞过了,这里没沙发。(推荐你看《新语丝》,有闲心的还可以去找找,看到底在加州理工的CS博士列表里面有没有唐峻)
5、写回忆录不是为了要显摆什么,记忆中是什么样就怎么写(当然,记忆重构是无法避免的)。本人绝不像某些国内伪专家一样装B,别人说什么东西好的时候,
非得过来插一句说“我XX年前就见识过了”。那种人我最讨厌了,所以本文绝无半点那种倾向。所以,如果想跟我学装B也不要往下滚动了,我这人的特点是有一
说一,认为自己好的也说,认为自己差的也说。(装B最好的方法是把一些人人尽知的东西,另一群不知道的人中传播,最好自己写BLOG来传播,参考经典著作
而不要直接抄袭,这样最能装B!)
6、本人今年30岁,在1990年的时候我11岁,科特学习机也已经上市,已经具备了学习计算机的生理上的可能性,和客观条件上的可能性。各位福尔摩斯和柯南们可以回家了。

Basic

Basic是我编过的最多程序的语言,没有之一。虽然后来工作后也写过一些30-50MB
CPP源码的项目,但我一直坚信BASIC是我写过最多程序的语言(大约是因为易得性直觉吧,估计真实数据不是这样的)。当时的BASIC是我自己唯一拥
有的计算环境——科特学习机的F-BASIC。Basic是我见过的第一种编程语言,在我还没学会打字的时候就开始用它编程了。当时最大的愿望是写一个游
戏程序。现在回想起来,这算是家长禁买游戏卡带给逼出来的发奋图强了。

当时的F-BASIC里有背景图可以组成画面,有超级马利中多数的卡通角色可以用程序控制。编写一个游戏程序从技术上看起来是可行的,而且我还有大
量的时间,没有资金预算的问题——虽然这个项目的可行性评估完美通过,但最终还是理所当然地失败了,这是我人生中的第一个失败的软件项目,住在100公里
外的表弟最终也没有能够玩到我写的游戏。原因倒是很简单:F-BASIC没有BASIC中的陷阱编程(一种类似于中断的东西,可用来捕获键盘输入),无法
及时控制卡通人物行动,运行速度也太慢。这件事情的“蝴蝶效应”直到现在还余波未消——在讨论可行性的时候,我总是习惯于搞清楚“是不是真的可以”,不满
足于从文字中求证,而是要测试过才放心。(当然,从另一个角度来看,所有的技术问题最终都是管理问题,这就是另外的话题了)

虽然游戏项目可耻地失败鸟,但收获还是有的。最大的收益就是学会了将问题转换为计算机表达,比如讨厌的约瑟夫问题,我一直不会用公式计算,都是在纸
上画圈圈和叉叉,挪到计算机上还是挺节约白纸的;小学奥赛的经典名题“鸡兔同笼”在穷举法面前也不堪一击(虽然有无数求解公式,但我一直记不住);在《世
界数学名题趣谈》上看到的那个可以计算PI值的无穷展开的算式,我也是没有用笔算的耐心的(如果让我也算出几百位PI之后发现出错了,同样也会吐血的),
所以,写个分数运算程序,用计算机来运算还是很爽的——虽然当时的字串最长仅允许32字节,即使拼起来用,最终算不出几位有效数字。

在这种简陋的F-BASIC中,我还体验了一把“多媒体编程”。使用F-BASIC中的PLAY语句,播放三个声部的伴奏乐谱,然后录下来给音乐老
师作教学用,作为交换,我可以弹她的电子琴。因为直接写那些不断重复的“CDEFGAB”唱名字串很繁,我开始用程序来生成字串,这是我第一次接触到程序
和数据之间的相互转化问题。但很遗憾地是,F-BASIC不能由数据生成程序(如果有向磁盘LOAD和SAVE的标准BASIC倒还可能,F-BASIC
是向录音机存储数据的)。后来当我见识到了eval之后不由得大喜过望——数据向程序转化的东西终于有了。

除了这些之外,BASIC对我的负面影响也很大,比如良好命名,模块划分等方面,它带给了我许多不好的习惯。这些在后来学习LISP的过程中阻碍了
我很长一段时间,后来才慢慢改掉。记得有句名言说第一个学BASIC的程序员不会是好程序员,但我感觉这话太过绝对了。或许它表明了一种趋势和倾向,但并
不是一定如此。人,长着脑袋,就是用来学习和改进的。

dBaseIII

中国最早的信息化就是用的这玩意,无数个单位买来“先进”的286微机就是为了“会计电算化”或者“电子信息化”,所用的工具九成九都是
dBaseIII。当时的教育台里也总会有一个戴着龟壳大眼镜的谢顶老大爷,操着难懂地普通方言话,来讲解dBaseIII。我一直没有把dBase系列
看成一个真正的计算机语言,最初以为它是数据库,现在觉得它是个带一定编程手段的查询语言。当时听说它比COBOL要先进不少,所以为了迈向“高大全”的
目标,就把它顺便也学了。后来的《跟我学电脑》丛书,第四册整本讲的都是dBaseIII,我翻了无数遍,在纸上默写语法和程序,并且将样本数据进行了演
算,最终搞明白了这种“语言”。借着为某些单位修理dBaseIII系统的机会,我“偷”到了不少上机时间。另外,在纸上推演dBaseIII数据的时
候,也被迫学习了索引/二分之类的基础知识,认识到了算法和数据预处理的重要性,为后来学习《数据结构》等打下了基础。

Lisp

Lisp一直是我最喜欢的语言,没有之一;但LISP也是我一直没有能够掌握的语言之一(这回有“之一”了)。

我是在《跟我学电脑》那套从书中的《计算机语言发展历史》章节中知道LISP的,而且听起来它有一个很牛B的名字——人工智能语言。当时的中央电视
台的译制片栏目放了一部195x年的美国电影《地球停转之日》(不是后来Keanu
Reeves主演的那个翻拍版本),那里面的机器人功能很牛B,而且能听懂外星主人的语言,甚至人类小妞学着说的时候,它还知道把人类小妞给保护起来——
我当时就认定这机器人一定是人工智能的了。于是就买了LISP的书来学习。这本书里讲的是Sun工作站上的Common
LISP,还附带讲了LISP机的辉煌历史——这让我后来很自然地就接受了“用IDE工作”的理念,而且在相当长的一段时间排斥命令行编译(直到后来学了
GNU
MAKE才改正过来)。当然,对于LISP机关掉GC等待内存耗尽的故事,那本书里是不会讲的。这也是中国“学者”的通病,如果他说什么东西是好的,就只
说优点不说缺点。这一点读书时一定要注意。

LISP对我来说的一大特点就是自然,计算机不像BASIC那样地讨厌,而是变成了一个很自然的描述工具。现在想来,这和LISP的历史渊源是有很
大关系的——LISP最早就是John McCarthy发明的一种数学符号,而不是一种编程语言。只不过他的一个学生偶然在IBM
704机器上实现了可以解释执行的计算机语言LISP——关于IBM 704 blah
blah这一大段是我死记硬背的,我这辈子还没见过这种机器,估计也没机会见识了。

正因为LISP的原始发明意图就是在纸上推演的数学符号,所以使用它的时候完全感觉不到太多的障碍,这种障碍在别的语言中有很多表现,这里就不一一
举例了,相信大家都有体会。LISP的这个渊源,对当时的我来说,还有一点有着非同寻常的意义:它可以在纸上演算并求得结果,求解过程是可以直接用人类的
大脑来做的,而不像C语言那样几乎不得不用机器语言来做。举个例子,虽然CAR这个函数名称的由来和寄存器有关,但是它却有着非常直观的含义——砍掉
LIST中的第一个元素:(car (1 2 3)) -> (2
3)。至于为什么我得在纸上演算,原因很简单:在那段时间里,如果一个中国的初中生能够接触SUN的小型机,那他一定是牛B到不能再牛B的人物——很明显
我不是,所以我只能在纸上演算。

虽然LISP很直接和自然,但当时的我只有初二数学水平+一门粗浅握的《逻辑代数》,又没有太多的编程实践经验,所以对于某些东西的掌握还是很困难的,比如“闭包”这个怪物的意义,就让我困惑了很多年,直到后来看到了它和对象的等价式后才恍然大悟)

学习LISP对我的影响很大,从小的方面来看,有“看得见的万能之手”——完美的MACRO系统;递归——人来负责简洁清晰的算法,机器来负责提高
运算效率;GC——白胡子老管家式的周到服务;程序和数据的大一统——后来知道这叫S表达式;IF-ELSE——这个也是LISP的发明人John
McCarthy在LISP里发明的(不是ALGOL
60),嗯,我承认这一条基本上是用来刁难人的;从大的方面来看,学习LISP让我开阔了视野,在后来的许多年里,都只把C风格的语言当成低级语言,而没
有陷入语言成瘾的状态,对于2000年以后流行的各种语言也持有一种积极接受的态度——本来这些就都是从LISP里拿来的嘛!记得有一句名言,大致是
说:1、世界上只有两种计算机语言,C风格的和LISP风格的;2、一个现代语言的发明,就是在C的风格基础上借用一些LISP的“先进”概念(比如精通
LISP的James Gosling发明了带有GC的JAVA)

Prolog

最早知道Prolog还是在《跟我学电脑》那套书里知道的(若干年后才知道是自大的法国人强行发明的),当时书中称这种语言是“下一代的计算机语
言”,是计算机业的未来。为了“不输在起跑线上”(当时很流行这句话),我立即就去把书买了回来,虽然不时地翻出来看,但一开始根本就没看懂;而且这本书
上说:对于学生来说,同时学习Prolog和LISP是很难的事情,因为风格不统一。我当时在学LISP,所以Prolog就放弃了好长一段时间。

后来在某一天,偶然翻看Prolog的时候,我突然间就顿悟了(不过我没有像阿基米德那样光着屁股裸奔)。比如在Prolog里定义一个逻辑关系,
根本不用像BASIC那样绞尽脑汁定义变量存储,也不用像LISP那样编写函数去递归求解,如果我说farther(A,
B).的话,那就是有一个A是B的父亲,至于A和B是什么,Prolog不知道、也不必知道,甚至对于father这个谓词它也不知道,它只知道这其中的
逻辑关系。当然,如果仅仅能够接受这样的输入,也没什么意思,但Prolog可以在这些云山雾罩的关系的基础上,继续定义逻辑关系,并且最终还能自动求
解,比如:定义一个grandfather,就可以在father的基础上定义谁是谁的爷爷(多说一句:Prolog默认没有交换律——请按群论来理解这
个“交换律”的意思)。

过去学的种种语言,无论是LISP、C++还是BASIC,编程的人都得替计算机想出如何求解的过程来(不论看起来复杂的迭代,或者看起来简洁的递
归,其实都是在定义求解的过程),而且往往还得发明一些东西来帮助计算机:比如用BASIC这样的东西来求解约瑟夫问题,还得用自定义规则,用来模拟语言
本身不支持的链表结构。但是Prolog就不一样了,它就像一个解题机器一样,你告诉他一堆事实和规则,然后就可以提问了——完全不需要告诉它解题的“过
程”。Prolog其实也并不知道答案“到底是什么”,但是它可以按照你定义的规则求解出你所需要的答案(可能需要多打几次分号)。至此,我发现我的逻辑
代数白学了,学一个简单的Prolog语法就全部解决了嘛!

从那以后,我一直疑惑为什么LISP被称为人工智能语言而Prolog不是。而且“谓词”这个概念被我深深地记在了心中。到后来听说
ISO14882
C++98标准中竟然有谓词Pred,我着实兴奋了好久,但后来仔细一研究,原来跟Prolog的完全不是一回事。不过,C++模板编程在某些方面来看倒
是很有Prolog的风格,这也是有一段时间我不自觉地陷入了“template误区”的原因之一。

C++

借一句当年流行的歌:“你这样,一个语言,让我欢喜让我忧……”。最早我学C++仍然是因为《跟我学电脑》这套丛书,那里面介绍了B语言转化为C语
言,然后升级为C++语言(根本没提和UNIX的关系!)。既然要学,那我就学一个最好的吧!于是就略过了C,直接学的C++。所以在之后的10多年里,
我一直很鄙视“学C++必定要先学C”这样的说法。当时买的是张国锋写的C++的书,大约是91年版或者92年版的,只是在讲语言,没有讲编译、链接和调
试。因为我是BASIC出身,又喜欢LISP,所以在“如何将程序变为机器码”这一环节是一直是缺失的,直到后来整了一套Visual Studio
97(VC++
5.0)的光盘才真正开始熟悉整个的编译-调试过程。我还记得第一次碰到“找不到链接符号”这个错误时,我用了好几天才搞明白是函数体忘了写。在这方面的
知识一直仅仅是够用,直到后来在做过一个集成开发环境(IDE)后才得到了加强:许多问题都是在解析过OMF文件信息之后才真正理解的。因为自己有这一段
经历,所以我在教别人的时候一直强调:第一天就必须要上机来熟悉开发环境。懂得如何生成代码和调试代码,是作为一个编译型程序员必不可少的技能。

C++的教材在讲class的时候喜欢用复数(complex)作为例子。对于当时只有初中二年级数学知识的我,这就不啻于天书了,许多年一直没能
明白虚、实分量的相加代表了什么。还好里面有一个动物的比喻能够帮我理解OO的概念。但也仅限于封装、继承、多态等基础知识,很长一段时间我没有意识到
C++是多范型的程序语言。后来我学习C++开始转向“实用”这个“目标”(其实是学Windows
SDK):先是学习了MFC,然后开发过许多控件和程序,帮老师做过学校的课题,往杂志投稿过一些VC程序,大约在99年左右,我开始有些飘飘然了,觉得
C++不过尔尔(其实是连C++和VC都没分清)——这种心理一直持续到大约一两年后,有一次偶然在CSDN上看到某装B人士,正在以极为不屑的态度批评
一个发贴者不懂“面象对象”,他祭出的武器就是OCP。经过google得知OCP的内容后,我不由惊叹“此为神器也!”,继而开始拜读Bertrand
Meyer的《OOSC》,从此再也不敢“翘尾巴”了。之后的许多年里,我一直在观察周边的人,发现许多人的OO教育从一开始都是错的。我认为这不仅仅是
我本人的一个教训,也是教育的失败:当你让学生接触到某种东西的时候(例如OO),只给他看一些零碎的基础概念(封装、继承),教一些基本的实现手段(语
法),从来不说这种东西的思想精髓在哪里(OCP/LSP/etc.),也没有提供任何延伸阅读材料,反倒是在一个封闭的小圈子里不停地说这东西好,这东
西就是某个样子的——事实上这个“样子”却违悖了其中的精髓思想,而且一说就是十多年不间断(因为教材是抄来抄去的?)。若干年后,某些曾经被错误教育的
有识之士终于意识到了问题,从国外重新引进了原本的精髓思想。但也已经无法成为主流了,错误积累的太过深重,OO本身已经完全毁掉了。

说到C++几乎不得不说《设计模式》。国内的中文译本大约是在2000年出版的。在当时设计模式很受人们推崇,给人一种万能药的感觉,仿佛有了它中
国就不必再担心软件结构的设计问题了。在我看来这又是典型的“大炼钢铁”式的思维——一味地追寻成功者的足迹,不管是不是充分条件(甚至不管是否必要)。
我一直觉得设计模式在国内吹嘘得过分了。从OCP等原则出发,可以推出许多模式;从LISP语言看过去,许多模式就是一陀额外的屎——但是这个想法一直不
敢太公开(人微言轻啊),直到后来读到Peter Norvig的那个Presentation。

C++的98标准及相关的一些知识是在CSDN论坛上得知的,后来疯狂地购买和阅读C++的相关书籍,几年后名单上的差不多有20本书以上。至此,
算是重学了一遍C++(书单中还真包括一本《C++
Primer》)。看过之些书这后,在之前的OO的基础上,明白了对象模型的细节,熟知了STL和模板的应用(甚至有超级古怪的应用),熟记了一些常见的
陷阱和Workarounds,甚至还背诵过三字节操作符这样罕见的东西。现在回想起来,学习这些东西的机会成本,其实还是蛮高的。

古老的C++语言因为泛型编程而焕发了“第二春”,但我对C++语言的兴趣却开始慢慢消失。虽然一直还在关注着这一领域,但也只是在关注了。从网上
随处可见的关于C++的争论之中,我能体会到一些人不是因为理智,而是因为某种情结和瘾癖而在捍卫着C++,他们的思维陷入了一个怪圈中。一开始我觉得这
是因为见识的问题,后来意识到,归根结底还是因为open
mind的问题。等到了“否定C++以外的东西”成为了你的第一反应的时候,或者当你总是下意识地寻找和传播C++的好处的时候,你的大脑很可能就开始封
闭了。这是一件很危险的事情,而且更危险的是你自己很难意识到这种状态。有一段时间,我曾经几乎要陷到这种状态当中去,幸运地是,偶然有一次聊天时说到
LISP,在我向别人介绍LISP的强大的同时,我突然感觉到天灵盖处的一阵颤栗,仿佛冥冥之中的设计好的某段程序重新启动了,十年前学习各种编程语言时
的感受重新涌入了大脑,迫使几乎侵占了所有地盘的C++重新回归了它应该有的位置。后来LP推荐《心理学》给我看。在此之前,我曾经因为一本特别差劲的教
材,而误解心理学为伪科学——这一错就是十多年!在LP的推荐之下,我看了David
Myers的《心理学原理》,才终于接触到了真正的心理学(其它好书也有一堆,这里同样就不列举了)。学过了心理学之后,我对自己当时的心态也就有了一个
更加清醒的认识。我决定把这些写下来的原始动机,也是为了总结+自醒,也供他人借鉴。

Pascal

将Pascal写进来有点时间线的问题,因为Pascal是在上高中为了参加奥赛而学的。但既然上面讲C++时,已经说了后来发生的事情,这里也一
并说一说吧:Pascal语言,我也是对着书在纸上啃下来的,没有上机。有了前面学过的那些语言作为基础,学Pascal只用了不到一周的课余时间。这个
事情对我的影响却是负面的,有很长一段时间,我错误地以为学习一门新语言是简单地事情——有了原来打的基础,学习语言本身的确是很简单,但是我却忽略了程
序库的重要性。我一直不会JAVA语言就是因为它的语法太平淡了。虽然我在上大学时,也有过一本1000多页的《JAVA内裤大全》,但JAVA还是被我
给错过了。

 

【上篇】
【下篇】

抱歉!评论已关闭.