- 内容提要
- 序 1:程序里的世界
- 序 2:最后一层表象
- 关于本书
- 致谢
- 引言:简单的本源
- 篇一:计算系统
- 第 1 章 数,以及对数据的性质的思考
- 第 2 章 逻辑
- 第 3 章 抽象
- 篇二:语言及其面临的系统
- 第 4 章 语言
- 第 5 章 从功能到系统
- 篇三:程序设计的核心思想
- 第 6 章 数据结构:顺序存储
- 第 7 章 数据结构:散列存储
- 第 8 章 执行体与它在执行过程中的环境
- 第 9 章 语法树及其执行过程
- 第 10 章 对象系统:表达、使用与模式
- 篇四:应用开发基础
- 第 11 章 应用开发的背景与成因
- 第 12 章 应用开发技术
- 第 13 章 开发视角下的工程问题
- 第 14 章 应用程序设计语言的复杂性
- 篇五:系统的基础部件
- 第 15 章 分布
- 第 16 章 依赖
- 第 17 章 消息
- 第 18 章 系统
- 篇六:系统的基本组织方法与原理
- 第 19 章 行为的组织及其抽象
- 第 20 章 领域间的组织
- 附一:主要编程范式 及其语言特性关系
- 附二:继承与混合,略谈系统的构建方式
- 附三:像大师们一样思考——从 UML 何时死掉 谈起
- 附四:VCL 已死,RAD 已死
4.5 你真的理解这行代码吗?
绑定有很多种情况,几乎所有在程序代码中用到的标识,都存有绑定的问题。最常见的例如变量 9 :
var aNum = 100;
上述一句代码(的语法),对应着三个语义:
- 有一个标识,记为
aNum
; - 标识所指代的数据,其值是可变的(即,变量);
- 该数据当前值为 100。
对于大多数语言来说,第二个语义是一项执行过程中的限制,亦即表明任何可以访问到 aNum 标识的代码都可以改变它的值。为了简便,我们暂不讨论这一个语义的绑定问题。但第一、三个语义所述的:
有标识 aNum
,其数据当前值为 100
就明显作用于我们的计算:如果数据无值,或值不确定,则我们无法进行后续的计算过程。所以对于代码 aNum = 100
,其在语义上的“值 100”将在何时被绑定到标识 aNum
,就是一个相当重要的问题。
以一个代码片段来看(相信我,这是实际可运行的代码):
1 2 3 4 5 |
|
根据我们对这段代码的语法约定,第2、5行决定了代码片段中的标识符的生存周期 10 。但在这个生存周期中, aNum
是何时有“值 100”的含义的呢?
对于这个问题,一些语言认为,表达“ aNum
变量具有初值 100”这样的语义,应该是计算过程的 前设 ,即对计算前提条件的声明。而声明并不是计算,因此声明语法与执行语法也应当分别对待。例如 Pascal,就处理为这样的语法(在 var
部分做声明,在 begin...end
部分处理执行):
1 2 3 4 5 6 7 |
|
另一些语言则认为,声明语法可以理解为对执行环境的预置,也有执行含义,因此可以允许“即用即声明”,例如 C。但是语义上,这是因“(需)即用”而进行的声明,不可能出现“已用”而未声明的情况。所以即使 C 语言,也会因为语义上无法解释,而判断上述代码 1 违例。
还有一些语言认为:
var aNum
是一个语义,它只表明标识 aNum
的存在,直到 函数调用 时才绑定另外一个语义:初始操作,亦即是为函数内所有存在的标识进行初始化。在这样的认识下,“代码1”中的
1 2 3 4 |
|
就具有了完整的语义。这个语义(即“初始操作”)与实际的计算机行为,是在把 process_part_one()
作为 函数调用 时,才进行绑定和实施的。其效果是:
- 在生命周期(代码3的2~4行,或代码1的2~6行)中,记有一个标识
aNum
;且, - 在该标识所处生命周期开始时,总会有一个初始化动作,使该标识具有一个初值: 无值 ;且,
- 设整个计算环境中, 无值 是一种值,记为
undefined
。
你可能已经知道,这就是 JavaScript 的实现方法 11 。进一步地,除开上述代码在生命周期上的解释之外,代码1被理解为:
1 2 3 4 5 |
|
我们看到,代码1中的语法:
var aNum = 100
所具有的两个语义(本小节开始处的语义 1 和语义 3)被分别绑定在 函数调用开始 和代码4的第4行;且一个标识的初值含义,总是明确地被约定为 undefined
。由此一来,上述代码1整体的语义就确定了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论