编程语言学习笔记
我在2021年秋季PL(编程语言)期末考试前学习的笔记。
堆管理/垃圾回收
1. 引用计数器(快速方法)
- 在每个单元格中维护一个计数器,存储当前指向该单元格的指针数 指向该单元格的指针数
- 当计数器下降到 0 时,回收单元格
2. 标记和扫描(懒惰法)
- 递归跟踪所有实时指针,将其标记为有用指针
- 扫过整个堆,回收未标记的单元格
- 同时关闭标记
3. 停止并复制(懒惰法)
- 将堆分成两半,所有新的分配都进入活动的一半
- 递归跟踪所有活指针,将发现的结构复制到 现在这一半成为活动堆
- 非活动半部分现在只包含垃圾;可以回收
4. 代际复制
- 跟踪单元生命周期,减少收集长生命周期结构的频率
收集频率
- 生命周期:它们存活的次数
5. 逃逸分析
- 指针的生命周期是否仅限于当前过程?
- 是:值可以存储在堆栈中,不需要分配或释放。
覆盖与重载
1. 重载
- 重载实现了运行时多态性(虚拟)
- 发生在超类和子类之间
- 方法具有相同的签名(相同的名称和参数)
- 运行时根据对象时间决定调用的方法
2. 重载
- 重载实现了编译时的多态性
- 发生在同一类中的方法之间
- 方法名称相同,参数不同
- 编译时决定调用的方法
静态绑定与动态绑定
1. 静态绑定
- 静态绑定在编译时发生并保持不变
- 通过默认约定指定类型
- 未明确声明的静态类型(如 auto)
- int x" - 在源代码中提供类型信息,编译时已知
2. 动态绑定
- 动态绑定发生在运行时(执行过程中),可以改变
- 通过运行时多态性指定类型
- 变量赋值时与类型绑定
- 高成本:运行时类型检查和解释
Prolog
% Tail recursion for length of list
len_acc([], Acc, Acc) :- !.
len_acc([_|T], Acc, Result) :- Acc2 is Acc + 1,
len_acc(Tail, Acc2, Result).
len(Lst, Result) :- len_acc(Lst, 0, Result).
% Tail recursion for factorial
fac_acc(0, Acc, Acc) :- !.
fac_acc(N, Result, Acc) :- N2 is N - 1,
Acc2 is N * Acc,
fac_acc(N2, Result, Acc2).
fac(N, Result) :- fac_acc(N, Result, 1).
% Max of list
max_acc([], Acc, Acc]) :- !.
max_acc([Head|Tail], Result, Acc) :- Head > Acc,
max_acc(Tail, Result, Head).
max_acc([Head|Tail], Result, Acc) :- Head <= Acc,
max_acc(Tail, Result, Acc).
max([H|T], Result) :- max_acc([H|T], Result, H).