主要程序设计语言发展
plankalkui, fortran,lisp, algol60, cobol, basic, pl/i,apl,snobol,
simula67, algol68, prolog, ada, smalltalk, c++,java, javascript, php,
python,ruby,c#。当然还有其他的,比如delphi,
erlang,haskell,scheme,clojure, scala, racket等语言
表达式文法的BNF和EBNF版本。
语法是一个四元组,文法的集合是一个元组,语义则是语法的“增强版”,对于语言的类型检查等都有重要作用。
一、语言设计的基本原理
1.1 语言评估标准
- 可读性:语法设计、抽象机制、表达简洁性
- 可写性:支持抽象、表达力、可靠性
- 可靠性:类型检查、异常处理、别名控制
- 成本:培训、开发、编译、执行、维护成本
1.2 语言分类范式
- 命令式语言:C, C++, Java, Python
- 函数式语言:Lisp, Haskell, ML
- 逻辑式语言:Prolog
- 面向对象语言:Smalltalk, Java, C++
- 脚本语言:Python, JavaScript, Ruby
二、语法与语义
2.1 形式化语法描述
- BNF(巴科斯范式):上下文无关文法的标准表示法
- EBNF(扩展BNF):添加可选、重复等操作符
- 语法图:图形化表示语法规则
2.2 属性文法
- 将语义信息附加到语法结构
- 综合属性 vs 继承属性
- 用于静态语义检查
三、名字、绑定与作用域
3.1 绑定时间
3.2 存储绑定与生存期
- 静态变量:整个程序执行期间存在
- 栈动态变量:过程调用时分配
- 显式堆动态变量:程序员显式分配/释放
- 隐式堆动态变量:语言运行时管理
3.3 作用域
- 静态作用域(词法作用域):基于程序文本
- 动态作用域:基于执行调用序列
- 作用域与可见性规则
四、数据类型
4.1 基本概念
- 描述符:存储类型信息的数据结构
- 对象:具有值和类型的存储单元
4.2 原始数据类型
4.3 字符串类型
4.4 用户定义类型
- 枚举类型、子界类型、数组类型
- 记录类型、联合类型、指针类型
4.5 数组类型
4.6 记录与联合类型
五、表达式与语句
5.1 表达式求值
- 操作符优先级与结合性
- 操作数求值顺序
- 副作用与引用透明性
5.2 语句层次控制结构
- 选择语句:if-then-else, switch/case
- 迭代语句:计数器控制、逻辑控制
- 无条件分支:goto的争议与替代
六、子程序
6.1 基本概念
6.2 参数传递方法
- 传值:实际参数值复制到形式参数
- 传结果:结果复制回实际参数
- 传值-结果:传值与传结果的组合
- 传引用:传递地址
- 传名:按需求值(已很少使用)
6.3 参数类型检查
6.4 重载与多态
- 重载:同一操作符/函数名多个含义
- 多态:参数或返回值的类型可变
七、面向对象编程
7.1 核心概念
- 抽象数据类型:数据与操作的封装
- 继承:代码复用与特化
- 动态绑定:运行时方法解析
7.2 设计问题
- 单一继承 vs 多重继承
- 动态绑定与效率权衡
- 嵌套类与可见性
八、函数式编程
8.1 数学基础
- 数学函数:映射定义域到值域
- λ演算:函数定义与应用的 formalism
8.2 函数式语言特性
- 一等公民函数:可作为参数和返回值
- 高阶函数:操作函数的函数
- 引用透明性:表达式可替换为其值
- 惰性求值:需要时才计算表达式
九、逻辑编程
9.1 基本概念
- 命题:可判断真假的陈述
- 谓词逻辑:量词与变量
- 子句形式:Horn子句
9.2 Prolog基础
- 事实、规则、查询
- 归结原理:逻辑推理机制
- 深度优先搜索与回溯
十、并发
10.1 基本概念
10.2 同步机制
- 信号量:Dijkstra提出的经典方法
- 管程:封装同步操作的高级抽象
- 消息传递:进程间通信的替代方案
十一、异常处理
11.1 异常处理设计
- 异常检测与处理分离
- 异常传播机制
- 继续执行 vs 终止执行
11.2 异常处理实现
十二、函数式语言实现
12.1 函数式语言特性实现
- 惰性求值的实现技术
- 高阶函数的编译策略
- 尾递归优化
十三、逻辑语言实现
13.1 Prolog实现技术
- 合一算法:模式匹配机制
- 回溯控制:搜索空间管理
- Warren抽象机:高效执行模型
十四、代码优化技术
14.1 优化分类
- 机器无关优化:中间代码级别
- 机器相关优化:目标代码级别
14.2 常见优化技术
- 公共子表达式消除
- 循环优化:代码外提、归纳变量消除
- 强度削弱:用廉价操作替换昂贵操作
学习建议与思考题
关键思考方向:
- 不同编程范式如何影响问题解决方式?
- 语言设计中的权衡:表达力 vs 安全性,灵活性 vs 性能
- 现代语言如何融合多种范式特性?
- 语言特性如何影响编译器设计与实现?
实践建议:
- 用不同范式语言实现同一问题,比较差异
- 研究流行语言(如Python、Rust、Go)的设计选择
- 实现简单的解释器或编译器加深理解
- 关注语言设计的最新趋势(如领域特定语言、可验证语言)
核心收获:编程语言不仅是工具,更是思维方式的体现。理解语言设计背后的原理,能帮助我们更好地选择和使用语言,甚至设计适合特定领域的语言。语言设计的核心是在各种约束(表达力、安全性、性能、易用性)之间寻找平衡点。