- 在线时间
- 6 小时
- 最后登录
- 2015-5-5
- 注册时间
- 2015-4-8
- 听众数
- 9
- 收听数
- 3
- 能力
- 0 分
- 体力
- 111 点
- 威望
- 0 点
- 阅读权限
- 20
- 积分
- 49
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 27
- 主题
- 14
- 精华
- 0
- 分享
- 0
- 好友
- 7
升级   46.32% TA的每日心情 | 擦汗 2015-5-5 09:17 |
|---|
签到天数: 13 天 [LV.3]偶尔看看II
- 自我介绍
- 往往
 |
因为看到谈lisp的一些书,提到70年代学术界在现代编程的主流是lisp和汇编、fortran。这个并不奇怪,因为那个时候很多现代的语言,比如c,pascal还没有发明呢。然后个人计算机的主流编程是basic和汇编。! X: p7 i# @5 y$ Z9 N$ s2 h
7 x' a) d+ R9 k6 b1 T为什么?一个原因就是当时的计算机内存太小了。还活到现代的古代编程语言里面,fortran是靠不断更新语法特征才留下来的。早期的fortran除了有算术表达式解析,和机器码无关两个特征,其实和一个比较完善的有宏的汇编语言的复杂程度查不了多少。% s9 G; F$ g# D& H, _4 y
( X: G- E& P9 ^; R6 Z
现在很多人都觉得写汇编好厉害……其实不用现代语言的一些特征,写汇编并不难,熟悉c的写个三天就能学会写汇编,汇编难的是记住一大堆调用的固定用法,这些并没有什么难度,就是明明是计算机擅长的东西让人类来每天写同样的东西很反人类罢了。其他一些if之类的结构,用个宏就能模拟的差不多了。估计写lisp或者java的人看用c的那些人在非系统软件里面康慈康慈写内存分配也是这个感觉吧。8 v/ b9 s& t. z* U
, ]5 A; `9 C) h早期的basic也是这个原因,比尔盖兹写的那个basic,包括现在属于bios和操作系统的io等全部库,全部程序大小只有20k不到。现代语言就算最精简的lua,不算操作系统,也有300多k。而在早期计算机里面,300k内存哪怕是一次性rom也比计算机本身贵多了。
# E u5 X/ `( m3 b$ \% i0 N) f2 I8 u1 `9 e" y' g- J
lisp的优势是它是基于数学的,所以核心部分非常小,1k内存就能完成全部解释器,剩下的功能都可以用lisp本身代码来实现,所以也是那个时候高级语言唯一的选择。lisp里面大量用到表,而这个表是用链表实现的,这也是节省内存的一个巧妙设计。因为链表在取它的后半部分,或者在头部添加内容的时候(在尾部进行改变则不行),可以共享后部的相同部分,这样就可以在进行数据操作的时候节省大量拷贝内存、分配新内存的工作。这也是lisp最早发明内存垃圾收集器的原因。$ @! D: L0 d( T: a0 u5 Y$ D1 G! v% u
. y( h3 w7 {1 C( `; M
c语言发明的时候,节省内存用的办法就是把编译任务尽可能拆开,中间结果用文件缓存,进行下一步的时候就把上一部处理的程序丢出内存。
8 I- t: ~1 X& ]2 b: l2 E具体说,你要统计一个1M的文本里面出现了多少个the,需要多少内存?只要几十个字节。因为你扫描文件的过程当中无需保存中间结果,只有在扫描到了符合一半的时候需要保存一下中间结果,然后是一个变量。同样,你编译的时候,只需要一个符号表(保留字,常量变量,宏,函数定义)和一个临时符号表(函数内部变量),然后一个函数相关的跳转表(每个函数内部的for循环,if语句和goto语句要跳到的地址),一个数学表达式解析表,剩下的因为都是上下文无关,所以一边读,在缓冲区转换,存到目标文件,不用放到内存。通共只要几k就行了。如果符号表太大,甚至符号表也可以放到临时文件里面。真正占内存的都是上下文相关的数据。
" K# D7 a7 l- ^* W2 U, R( @0 H所以大家会看到头文件这种设计,因为这样就可以不用把其他文件的编译信息都读进来。函数要定义才能使用也是一样。花括号和+=等操作也是为了减少程序空间大小。因为当时内存实在太宝贵了。著名的switch语句的缺省没有break也是一样的。
+ |) N3 i. V, J0 j8 F/ c7 k U- X! X; z( Q/ H3 g
从这一点看,和c同时发明的pascal,都是algol语言的继承者,在这一点上就设计的更好一些,抛弃了很多工程上的小聪明。如果不涉及系统编程,比如大量频繁的内存分配,两者的语法几乎是等价的,而pascal语言的程序相对而言清晰得多,更不容易产生错误。库的处理,中间代码P code的处理,都非常巧妙。如果不是c那样的超级通用语言(可以进行系统编程)的话,pascal本来可以成为一种更流行的语言,从而让现在的软件工程更正规一点。毕竟,个人电脑发明后,由于摩尔定律,内存的增加让c为节省的那点内存进行的操作完全成了多余而添麻烦的行为了。
1 ^* A5 P1 W$ ]3 I) x5 _
, }) M; T* m5 o6 f* c具体说来,lisp的设计导向、学术导向是最严重的,尤其是scheme系列(common lisp也有很严重的工程师倾向)。pascal也是比较学术的,C就是完全工程师向的。但是在语言复杂程度和抽象程度而言,两者是差不多的,比早期的colbol和fortran高了一个级别。
; F7 f* o- ^- t% q
( `5 q* Y* h1 |至于后来的c++,java,ml(ocaml,F#,haskell)等属于更高一个级别的设计。而perl,php则是纯工程导向、设计度比较低的产品。ruby,python,lua则是一开始就意识到了将来的发展,为未来扩展做了准备的脚本语言。
* \, @' A6 f$ `0 m0 b; q( ^, [) B
脚本语言现在中间代码(加速运行)、属性表(动态类型)、类或者闭包(用于绑定数据和处理数据的程序)基本都是标配了。这使得程序比过去的脚本语言复杂多了。4 w. u' k5 I# O. C3 v
$ K; g' I, T/ @ |
zan
|