程序原本(五十一):程序设计的核心思想——执行体与它在执行过程中的环境(从静态到动态)

阅读数:27 2019 年 10 月 1 日 16:06

程序原本(五十一):程序设计的核心思想——执行体与它在执行过程中的环境(从静态到动态)

相反地,一个语言环境中也可能存在四种与上述静态语言约定不相容的情况。

其一,在执行之前存在标识但没有任何已知的值,代码运行时该标识存有绑定任何值的可能,称为动态绑定4。例如下面的代码行在 JavaScript 中表示环境中有一个标识age,但直到该行代码执行时,age所指示的存储中才会有值 20:

4 动态 / 静态绑定这个概念被用在很多的地方,我们这里只明确地阐述其中的一种形式。即一个无类型、无值的变量,可以动态绑定一个值来赋予它类型的概念,即后文的动态类型。除此之外,我们并没有讨论在静态语言中存在的一个有类型变量,在执行期进行绑定(赋值)的情况。

复制代码
// 示例 1
var age = 20;

与此相对,我们称标识在运行之前就具有了值和类型的情况为静态绑定。例如在 Delphi/Pascal 中:

复制代码
// 示例 1
Var Age : Integer = 20;

其二,对于已经(动态或静态)绑定过的标识,如果通过写值的方式能够使之具有新的数据类型含义,我们称为动态重写5。对此前的示例 1,我们可以有如下代码:

5 重写一个具名函数看起来是一个动态特性,但它其实并没有改变标识上的数据类型,所以不作为这里的动态重写来讨论。从另一个角度来说,具名函数的重写与i++的性质是一样的。

复制代码
age = "unknown";

这会导致age具有新的数据类型,而这在 Delphi/Pascal 中会被视为违例。

其三,动态绑定或是动态重写导致标识具有不同数据类型含义的情况,称为动态类型。示例 1 中的age在动态绑定发生之后,JavaScript 环境允许使用typeof()取得其类型为Number,但在绑定发生前则是未定义的6

6 Undefined在 JavaScript 中也是一个类型,但这是概念完备性的一种表现,并非我们这里讨论的数据结构。

其四,如果允许将(任意或特定数据类型的)数据作为代码片段加以执行,则称为动态执行。例如:

复制代码
eval("dynamic_code_text");`

当然,这也意味着多数脚本语言具有动态执行的性质,只要它们能读取文本文件内容并执行。

对于支持上述(“静态绑定”是显然被排除在外的)四种性质中的一种或多种性质的语言,我们就称为动态语言

所以我们此前将部分讨论限定在“静态的、编译型”语言之中,实在是有着严苛的条件:既要能直接编译成机器语言,又要能明确有标识和数据类型含义。接下来,我们的讨论则要广泛得多。不过此前讨论的那些性质,在后续讨论中也仍然是合用的——这本来就是我们构划这样一个讨论路径的原因。

评论

发布