如何学习一门编程语言

2024-12-151 出链
  • S:在学习和实践“如何学习一门编程语言”时,需要建立统一的概念和问题边界。
  • C:相关概念、实现机制和工程取舍容易混在一起,导致只记住结论而无法判断适用条件。
  • Q:“如何学习一门编程语言”要解决什么问题?它的核心抽象、工作机制和边界分别是什么?
  • A:本文围绕“如何学习一门编程语言”整理核心概念、关键机制和工程实践,并明确其适用边界。

语言是建立在操作系统提供能力之上的抽象系统。不同语言直接的区别不在于能力,而在于其抽象。可以把语言理解成对机器能力的不同投影,选择把哪些复杂度暴露给程序员。

语义距离:更贴近硬件?还是更贴近问题本身(数学)?后者是高级语言最大的价值? 人体工学:表达成本,认知负担;把需要程序员维护的不变量转移给语言的compiler/runtime;内存、并发、类型,从机器原语到可以被人类之间操作的概念。

三个坐标:距离硬件多远?距离问题领域多远?人体工学。

程序 = 数据 + 计算(操作)

  • 数据模型:表达值、组织值
  • 计算模型:对数据进行变换
    • 组织计算:控制结构
    • 约束计算:类型系统、副作用系统

控制结构引出命令式(描述怎么做:一系列变更指令)、函数式(描述结果是什么);不同的计算组织方式,形成不同的编程范式

  • 类型系统:数据与操作的合法组合;用一套静态或动态规则,对值即其组合方式进行分类、约束;
  • 副作用系统:计算对外界产生的影响

程序 = 编译期 + 运行时

编译期:利用静态信息,提前验证程序、生成代码并优化执行 运行时:表示值,管理系统资源,控制流管理,执行基础设施

如果是静态语言:语言如何在静态类型里提供动态能力,及相关成本(静态结构负责确定性,动态机制负责变化)。

性能、安全(类型、内存、并发)、表达力(抽象及成本、约束)

学习语法只是起点,还要理解语言在三个维度上的取舍:

  • 性能:值如何表示,内存由谁分配和回收,函数调用与动态分派成本多大,编译器能做哪些优化。
  • 安全:类型系统能排除哪些错误,内存和并发模型提供什么保证,又通过哪些逃生舱绕过保证。
  • 表达力:函数、接口、泛型、宏等抽象能消除什么重复;抽象成本发生在编译期、运行时还是人的理解阶段。正确代码容易写,错误代码难以表达。

不要孤立评价“快”“安全”或“简洁”。一种机制通常同时改变多个维度:动态分派提高扩展性,却可能阻碍内联;GC 降低内存管理负担,却引入运行时和延迟成本;强类型约束提前暴露错误,也会增加建模工作。

学习时选择一个熟悉的小问题反复实现,并追问:

  1. 编译器能证明什么,哪些检查留到运行时?
  2. 数据的布局、所有权和生命周期是什么?
  3. 错误、取消和并发如何传播?
  4. 抽象泄漏时,如何观察和调试底层行为?
  5. 性能结论能否通过 benchmark、profile 或生成代码验证?

思考方式

A language that doesn't affect the way you think about programming is not worth knowing.

  • 表达数据
  • 控制变化
  • 控制副作用
  • 隐藏复杂度

类型系统

类型系统本质上是一种受限的形式逻辑。程序在类型检查过程中生成一组约束,而编译器(或类型检查器)通过求解这些约束,构造一个关于程序性质的证明。

不同语言的类型系统差异,本质上在于它们选择了不同的逻辑片段与可判定约束,从而让编译器能够证明不同层次的不变量。

类型系统是编程语言中的自动化证明系统;不同语言的区别,在于它们选择了不同强度的逻辑,从而决定了编译器能够证明什么。

语言 主要变量(编译器关注的对象) 主要约束(受限逻辑) 想证明什么
Rust 类型、生命周期、所有权状态、trait、借用关系 类型一致性、outlives 生命周期关系、唯一借用规则、trait obligation、move 状态 内存安全、数据竞争安全、资源唯一释放
TypeScript 值的类型、对象属性集合、联合类型分支、泛型参数、控制流状态 结构子类型(structural subtyping)、集合包含关系、类型收窄(narrowing)、条件类型约束 JavaScript 动态值在静态阶段的形状正确性
Go 接口类型、方法集、类型参数、type set 方法集包含关系、接口满足关系、泛型约束、可实例化条件 类型是否具有所需行为,接口调用是否安全
Python(typing) 类型注解、变量类型、函数签名、Protocol、Generic 参数 名义类型(class hierarchy)、结构类型(Protocol)、类型兼容、Optional/Union 分支、泛型约束 提前发现 API 使用错误,保证大型代码库中的接口一致性
  1. https://www.infoq.com/presentations/rust-tradeoffs/
  2. Zig

评论