personal-website

Ground Oddity

所属分类:技术博客与个人站

记录 SICP、编程语言、系统工具、旅行与生活经验的个人博客。

Ground Oddity 是一个长期维护的个人博客,文章从编程和计算机科学延伸到工作、生活与旅行。归档中既有 SICP 和 Lisp 学习笔记,也有 LLVM 程序分析、Ruby 工具开发、终端音乐播放、Makefile 管理博客等技术实践;另有欧洲旅行和瑞典生活记录。首页以年份排列文章,读者可以从 RSS 或 About 页面继续了解作者。这样的结构保留了技术学习在不同时间的轨迹,让概念笔记与后来的工程经验并置。

Ground Oddity:从 SICP 笔记理解程序抽象

发布于 2026年10月21日更新于 2026年10月27日

Ground Oddity 首页与多年文章归档

抽象是发现重复计算模式

《SICP 笔记 - 抽象的艺术》从一个简单问题开始:如何计算整数区间中所有数的和。直接描述这一过程时,可以逐项遍历区间,把每个整数加入累计结果。进一步观察后会发现,许多计算都具有相同结构:从一组值开始,按某种规则生成下一项,并把每项与累计结果组合。若每次遇到新问题都复制一份循环,只替换其中的加法或条件,程序会逐渐出现大量相似代码。

抽象的作用,就是把这个重复结构提取成更一般的过程。求整数和、计算幂级数中的项之和、对一组数求积,可能共享相同的遍历与累积骨架,而“下一项怎么得到”和“怎样合并结果”有所不同。通过将这些变化部分作为参数,通用过程可以覆盖多个具体任务。抽象并不是把细节藏起来,而是明确区分稳定结构与变化规则,使读者能够更直接地看到算法之间的共同点。

SICP 笔记中关于抽象的文章

从具体过程到高阶组合

在程序设计中,函数可以接受数字、字符串等数据,也可以接受另一个函数作为参数。后一种能力让程序能够对“如何计算”进行抽象。比如累积过程可以接收一项生成函数和一个组合函数,前者决定每个位置对应的值,后者决定如何把新值并入结果。具体的求和或求积就成为通用结构的一种配置,而不是两段彼此复制的循环。

这种表达方式与高阶过程有关。高阶过程把函数视作可以传递和组合的对象,使我们能够描述算法的结构,而不必将每一个小步骤写死在一个函数里。在函数式语言中,这种风格通常非常自然;在其他语言中,也可以通过回调、接口或泛型操作实现类似的复用。关键是先确认变化点确实可以被清楚地抽离,再选择语言提供的表达机制。

抽象也有适用边界。如果只出现一次且逻辑非常简单,过早引入多层函数参数可能会让代码更难理解。若抽象把本来重要的业务规则隐藏在不明显的回调中,维护者还要跳转多个位置才能理解程序行为。判断抽象是否有价值,可以问:是否存在多个相似实现?变化点是否稳定且能命名?新的抽象能否让调用处更清晰?未来添加新案例时是否减少重复?这些问题能帮助区分有用的共性与表面相似。

数据抽象与过程抽象相互配合

程序抽象不仅可以围绕计算步骤,也可以围绕数据结构。一个模块可以通过构造操作和选择操作暴露数据含义,而隐藏内部如何存储。调用者不必知道点、区间或有理数在内存中如何表示,只需要使用模块公开的操作。这样实现可以在不改变使用代码的情况下调整,只要公开接口保持一致。

过程抽象和数据抽象共同构成程序组织的重要基础。前者将重复的计算模式抽离,后者将数据表示与使用方式分开。两者都强调接口:接口说明如何使用一个概念,内部细节则允许在不破坏调用方的情况下变化。SICP 的编程示例会逐步从简单过程进入复合结构与更高阶的操作,读者可以沿着这些例子观察抽象层级如何增加,以及每一层如何利用下一层提供的接口。

在工程实践中,抽象程度需要随着问题复杂度调整。一个用于格式化日期的函数可能足够解决当前需求;当多个系统都需要不同日历、时区和本地化规则时,可能需要更明确的接口和组件边界。抽象太少会重复实现,抽象太多则会造成理解成本。代码库需要随着真实变化演进,而不是为了追求通用性预先设计所有可能情况。

SICP 如何训练问题分解

SICP 的学习过程强调从简单模型逐步建立复杂程序。读者可以先写出明确、直接的过程,再寻找可以组合的部分;之后用函数参数表达变化点,并观察新抽象能否解决多个问题。这种练习训练的是问题分解能力:确定输入与输出,识别递归或迭代结构,区分算法核心与数据表示,再决定接口应公开什么。即使日常工作不使用 Scheme,这些思考仍能迁移到 Python、Go、JavaScript、Rust 或其他语言。

学习抽象时,配合运行程序和测试很重要。可以先用小范围输入验证结果,再检查边界情况,例如空区间、单个元素或倒置区间。若通用累积过程依赖单位元、终止条件和组合函数,就要确保这些约定对不同任务都成立。测试多个使用案例可以揭示抽象定义是否真的通用,或是否只是对某一个例子恰好有效。

博客中的 SICP 笔记记录了作者从课程概念出发的理解过程,适合当作阅读伴侣。读者可以先读 SICP 原书中的对应章节,再比较笔记如何解释示例,并尝试自行实现另一种累积任务。若发现解释与当前理解不同,可以通过运行代码、写出递归关系或查阅教材修正。个人笔记提供一种理解路径,但教材原文和实际实验仍是更完整的学习材料。

从理论笔记延伸到系统实践

Ground Oddity 的文章还覆盖 LLVM、程序分析、Shadowsocks 和终端工具。这些内容与 SICP 笔记处在不同层次:程序设计教材讨论模型与抽象,LLVM 文章涉及编译器如何分析或变换程序,网络工具记录则面对协议和系统环境中的具体约束。把它们放在同一档案里,可以观察抽象知识如何进入工程实现:清晰的接口与通用过程有助于组织代码,底层工具的限制则提醒开发者不能忽略运行环境和性能行为。

想从基础开始的读者,可以先浏览 SICP 笔记的抽象、递归与迭代主题,再进入 Lisp 或代码实践文章;有系统经验的人则可以从 LLVM 或网络工具文章开始。生活和旅行记录展示了博客除技术之外的另一面。通过 RSS 关注更新、通过年份目录回看旧文,读者能看到作者兴趣和工作经验随时间变化的过程。

Ground Oddity 的价值在于保留从学习概念到记录实践的连续脉络。它不是一门从入门到高级编排的课程,而是一组可检索的个人笔记。将 SICP 抽象文章与教材、代码实验及其他技术主题交叉阅读,能够帮助读者把“复用代码”提升为更一般的思考:如何识别稳定结构、清楚表达变化,并在通用性与可理解性之间找到平衡。

本文依据 Ground Oddity 首页与 SICP 笔记整理,程序设计示例为概念性介绍,细节可结合 SICP 原书与实际代码验证。

公开来源