为什么编程语言中会有函数、类、作用域等概念?
为什么语言设计者会设计出这样的语法?
多角度剖析编程核心概念,掌握编程语言共通的知识
程序设计语言产生的原因
我们为了获得更轻松便捷的体验而编写程序。但轻松便捷不等于偷工减料。偷工减料在前,痛苦在后,这不是真正的便捷。
懒惰:程序员的三大美德之一
大家听说过“程序员的三大美德”吗?Perl语言的设计者Larry Wall在其著作Programming Perl ①中提出,优秀的程序员具有三大美德:懒惰、急躁和傲慢(Laziness, Impatience and Hubris)。这就是俗称的程序员的三大美德。本节,我们介绍其中最重要的一项素质:懒惰。②
①中文版为《Perl语言编程(第3版)》,由中国电力出版社于2001年出版,何伟平译。②美德中“急躁”的意思是,程序员忍受不了程序执行的低效。“傲慢”的意思是,程序员容不得对错误不管不顾。懒惰(Laziness)
懒惰是一项为了减少总能量支出,而不遗余力地努力的素质。为了节省工夫,设计的程序逐渐被更多的人使用。单独回答每个使用者的疑问费时费力,于是,程序中开始标有注释。所以说,懒惰是程序员最宝贵的素质。也正因如此,本书才得以展现在各位面前。请参考急躁和傲慢的解释。
《Perl语言编程(第3版)》
Laziness有懒惰、懒散、慵懒等不同的翻译方式,总的来说就是让自己轻松、方便。但这不是追求一时轻松,而是选择能将轻松便捷最大化的方法。也就是说,在能达到相同目的的多种方法中,选取一种效率最高、效果最好的方法。
根据《Perl语言编程(第3版)》一书,Perl这一名字是来自Practical extraction and report language(实用的数据获取及展示语言)。可见,Perl是为了能方便地展示数据而发明的一种语言。
语言们各有各的便捷
前面说到程序设计语言是为寻求便捷而创造的。那么,为什么需要有这么多种语言呢?这是因为,大家对于便捷的理解因人而异。我们来看一下语言设计者们的目的以及他们是以何为便捷的吧。
何为“便捷”
语言旨在使什么变得便捷呢?是高速的代码执行?还是简单易于掌握的语言规范?抑或是轻松地理解他人编写的代码?
比如,C++是一种非常重视代码执行速度的语言。为了使编程实现相同目的时,执行速度不亚于C语言,C++语言的规范相应变得复杂了。
另外,Scheme是一种很重视语言规则是否容易掌握的编程语言。它追求语言规范最简原则,所以它的语言规范全部加起来只有紧凑的50页而已③。但是,对满是括号的书写方式存在抵抗情绪的人应该不少。
③准确来讲,在1998年第五版修订版前是这样的。第五版修订版是50页,2007年的第六版放弃了规范最简原则,增加到187页。然而,C++语言有着超过1300页的规则说明书。相比之下,Scheme语言算是非常紧凑的了。(这里的页数都是指日文版页数。——译者注)
Python是一种侧重于把代码阅读变得容易的语言。相对于Scheme语言,它更接近于C语言。熟练的编程人员会使用很多控制语句,并且会在结构层面通过缩进符来规范书写。相对应地,其速度不是特别快,语言规则也不那么少而紧凑。
各有各的便捷
语言的便捷之处各不相同。比如,用PHP语言编写Web服务很轻松,但它不擅长文字处理。相反,Haskell和OCaml这样的ML(Meta-Language)系列语言,编写处理语言文字的应用很便捷,但编写Web服务时就没有PHP使用得那么多了。
在不同语言中,既有便于个人独立实现复杂算法的语言,也有便于多个人协作实现大型作业的语言,还有便于书写一次性使用的测试类语言。
程序设计语言的选用因使用者目的不同而不同。不同语言致力于达成不同的目的。如果把为实现高速执行而设计的C++语言和为了便于代码阅读而设计的Python语言放到一起比较,说C++语言的可读性差或者Python的执行速度慢,这样的争论意义并不是很大。
……
第1章 如何深入高效地学习语言
1.1 在比较中学习
语言不同,规则不同
C语言和Ruby语言中的真假值
Java语言中的真假值
1.2 在历史中学习
理解语言设计者的意图
应该学哪种语言,我们无从所知
学习适用于各种语言的知识
1.3 小结
第2章 程序设计语言诞生史
2.1 程序设计语言诞生的历史
连接电缆
程序内置
FORTRAN语言问世
2.2 程序设计语言产生的原因
懒惰:程序员的三大美德之一
语言们各有各的便捷
2.3 小结
第3章 语法的诞生
3.1 什么是语法
运算符的优先顺序
语法是语言设计者制定的规则
3.2 栈机器和FORTH语言
计算的流程
如何表达计算顺序
现在仍然使用的栈机器
3.3 语法树和LISP语言
计算流
如何表达计算顺序
现在仍然使用的语法树
专栏 要确认理解是否正确,首先得表达出来
3.4 中缀表示法
语法分析器
规则的竞争
专栏 当你不知道该学习什么时
3.5 小结
第4章 程序的流程控制
4.1 结构化程序设计的诞生
4.2 if语句诞生以前
为什么会有if语句
为什么会有if...else语句
4.3 while语句--让反复执行的if语句更简洁
使用while语句的表达方式
不使用while语句的表达方式
4.4 for语句--让数值渐增的while语句更简洁
使用for语句的表达方式
不使用for语句的表达方式
foreach--根据处理的对象来控制循环操作
4.5 小结
第5章 函数
5.1 函数的作用
便于理解--如同一个组织
便于再利用--如同零部件
程序中再利用的特征
5.2 返回命令
函数的诞生
记录跳转目的地的专用内存
专栏 函数命名
栈
5.3 递归调用
嵌套结构体的高效处理
嵌套结构体的处理方法
5.4 小结
第6章 错误处理
6.1 程序也会出错
6.2 如何传达错误
通过返回值传达出错信息
出错则跳转
6.3 将可能出错的代码括起来的语句结构
John Goodenough 的观点
引入CLU语言
引入C++语言
引入Windows NT 3.1
6.4 出口只要一个
为什么引入finally
成对操作的无遗漏执行
6.5 何时抛出异常
函数调用时参数不足的情况
数组越界的情况
出错后就要立刻抛出异常
6.6 异常传递
异常传递的问题
Java语言的检查型异常
检查型异常没有得到普及的原因
专栏 具体的知识和抽象的知识
专栏 学习讲求细嚼慢咽
6.7 小结
专栏 从需要的地方开始阅读
第7章 名字和作用域
7.1 为什么要取名
怎样取名
名字冲突
如何避免冲突
7.2 作用域的演变
动态作用域
静态作用域
7.3 静态作用域是完美的吗
专栏 其他语言中的作用域
嵌套函数的问题
外部作用域的再绑定问题
7.4 小结
第8章 类型
8.1 什么是类型
8.2 数值的on和off的表达方式
数位的发明
七段数码管显示器
算盘
8.3 一个数位上需要几盏灯泡
从十进制到二进制
八进制与十六进制
8.4 如何表达实数
定点数--小数点位置确定
浮点数--数值本身包含小数部分何处开始的信息
8.5 为什么会出现类型
没有类型带来的麻烦
早期的FORTRAN语言中的类型
告诉处理器变量的类型
隐性类型转换
8.6 类型的各种展开
用户定义型和面向对象
作为功能的类型
总称型、泛型和模板
动态类型
类型推断
8.7 小结
专栏 先掌握概要再阅读细节
第9章 容器和字符串
9.1 容器种类多样
9.2 为什么存在不同种类的容器
数组与链表
链表的长处与短处
专栏 大O表示法--简洁地表达计算时间和数据量之间的关系
语言的差异
9.3 字典、散列、关联数组
散列表
树
元素的读取时间
没有万能的容器
9.4 什么是字符
字符集和字符的编码方式
计算机诞生以前的编码
EDSAC的字符编码
ASCII时代和EBCDIC时代
日语的编码
Shift_JIS编码对程序的破坏
魔术注释符
Unicode带来了统一
9.5 什么是字符串
带有长度信息的Pascal语言字符串和不带这一信息的C语言字符串
1个字符为16比特的Java语言字符串
Python 3中引入的设计变更
Ruby 1.9的挑战
9.6 小结
第10章 并行处理
10.1 什么是并行处理
10.2 细分后再执行
10.3 交替的两种方法
协作式多任务模式--在合适的节点交替
抢占式多任务模式--一定时间后进行交替
10.4 如何避免竞态条件
竞态条件成立的三个条件
没有共享--进程和actor模型
不修改--const、val、Immutable
不介入
10.5 锁的问题及对策
锁的问题
借助事务内存来解决
事务内存的历史
事务内存成功吗
10.6 小结
第11章 对象与类
11.1 什么是面向对象
内涵因语言而异的面向对象
对象是现实世界的模型
什么是类
11.2 归集变量与函数建立模型的方法
11.3 方法1:模块、包
什么是模块、包
用Perl语言的包设计对象
光有模块不够用
分开保存数据
向参数传递不同的散列
把初始化处理也放入包中
把散列和包绑定在一起
11.4 方法2:把函数也放入散列中
first class
把函数放入散列中
创建多个计数器
把共享的属性放入原型中
这就是面向对象吗
11.5 方法3:闭包
什么是闭包
为什么叫做闭包
11.6 方法4:类
霍尔设想的类
C++语言中的类
功能说明的作用
类的三大作用
11.7 小结
第12章 继承与代码再利用
12.1 什么是继承
继承的不同实现策略
继承是把双刃剑
里氏置换原则
12.2 多重继承
一种事物在多个分类中
多重继承对于实现方式再利用非常便利
12.3 多重继承的问题--还是有冲突
解决方法1:禁止多重继承
解决方法2:按顺序进行搜索
解决方法3:混入式处理
解决方法4:Trait
12.4 小结
专栏 从头开始逐章手抄