chapter 包括 some sentences,表示您应该假设过程 put 和 get 存在:
为了实现这个计划,假设我们有两个过程,put 和 get,用于操作操作和类型表:
(put <op> <type> <item>)
在表中安装<item>,由<op>和<type>索引。
(get <op> <type>)
在表中查找<op>、<type> 条目并返回在那里找到的项目。如果没有找到项目,get 返回 false。
现在,我们可以假设 put 和 get 包含在我们的语言中。
所以,现在我们必须要求澄清您的问题:
您是在问“如何实现像 install-rectangular-package 这样的过程,以便在评估 (install-rectangular-package) 之后,get 过程可以查找所需的操作?”
或者您是在问“get 本身如何工作?”
或者您是在问:“即使如果我们假设存在这样一个支持put 和get 的表,presented code 如何工作,它安装了多个不同的名称为 real-part(和 imag-part 等)的函数,即使一个 real-part 来自矩形包,而另一个 real-part 来自 Polar 包?"
如果您要问第一个问题,答案是:install-rectangular-package 只需使用适当的参数调用put 以扩展get 将访问的查找表。
如果你问的是第二个问题,那么你需要看看put 和get 是如何实现的,这将在第 3 章中讨论。但快速的答案是:你可以使用一个数据结构来存储put 插入的每个 {<op>, <type>, <item>} 三元组的记录。这本书描述了一种方法来做到这一点,你只需建立一个条目列表。
(put 和get 的任何实现需要做的主要有趣的事情是命令式地修改一些隐藏状态。本书使用set-cdr! 操作来做到这一点。使用某种形式的命令式操作的要求可能是他们等到第 3 章才描述put 和get 的实现的原因。)
如果你问第三个问题,答案是“被lexical scoping的魔力”
install-rectangular-package 的定义有一个内部定义集合,install-polar-package 有另一个内部定义集合。即使在两个定义中选择的名称之间存在重叠,安装 polar 包不会覆盖之前由 rectangle 包定义的功能。
(在此区分函数定义中使用的名称与函数值/对象(您可能认为是(lambda (x y) ...))本身很重要。即使install-rectangular-package 和install-polar-package 重用相同名称,它们正在创建不同的函数值,然后将这些不同的值放入put/get 表中,没有任何附加到最初定义它们的名称的意义。)
虽然书中put/get表的图片看起来像:
表中的条目是不是名称。它们是函数对象。 real-part 或imag-part 的其他本地定义不会影响install-rectangular-package 或install-polar-package 安装的条目;影响这些条目的唯一方法是调用 put 本身并使用匹配的<op> 和<type> 参数覆盖表中的前一个单元格。
关于词法范围和思考本地函数定义的方法的更多讨论,我推荐this part of HtDP(“HtDP”代表“如何设计程序”,它和 SICP 一样,是对编程的介绍,但写在一种比 SICP 更能说明问题的时尚;另见paper comparing SICP and HtDP。)