人人都能学会程序设计9多语境的操作

来源:互联网 发布:太平洋软件站官方网站 编辑:程序博客网 时间:2024/04/28 08:51

多语境的操作

 

根据前一章的说法,代码运行时会从USER 语境中查询单字的定义,其实不完全是这样的。

代码中的单字是可以从不同语境中查询定义的。为了证明这一点,这里再做一个实验。

步骤一,我先通过context函数,分别为苹果(Apple)与谷歌(Google)建立它们各自专

用的语境。苹果的语境叫做Apple,里面只有一个单字OS,定义为"iOS"。谷歌的语境叫做

Google,里面只有一个单字OS,定义为"Android"(安卓)。意思是这两家公司谈到OS(操

作系统)的时候,指的是不同的东西,Apple 说的OS 是iOS,Google 则是指Android。

步骤二,我建立两个代码方块,分别叫做Apple-fan(果粉)与Google-fan(谷粉),内

容都是[print OS]

步骤三是重点:通过bind 函数,让Apple-fan采用Apple 语境,让Google-fan采用

Google 语境。

步骤四,我通过insert 函数,把两段代码串在一起(把Apple-fanGoogle-fan的内

容都放到code 中)。我在步骤五证实合并正确。步骤六,执行这段代码,发现显示出来的结

果居然不一致,说明一段代码可以采用不同的语境。

为了加深印象,请看下面的慢动作分解。

 

Apple: context [ OS: "iOS" ]

Google: context [ OS: "Android" ]

为了方便解说,我假设上述两个命令行是一起执行的(就像是一个命令行)。

执行上述代码前,REBOL 解释器会在USER 语境内准备好ApplecontextOSGoogle

这四个单字, 并从LIB 语境中将context定义复制过来(LIB 语境中没有AppleOS

Google,所以无法复制这三者的定义)。执行此代码后,会产生两个新的语境,分别成为

USER 语境中Apple 单字与Google 单字的定义。最后USER 语境中剩下OS 的定义是特殊

unset(表示尚未设定)。

 

Apple-fan: [ print OS ]

Google-fan: [ print OS ]

为了方便解说,我假设上述两个命令行是一起执行的(就像是一个命令行)。

执行上述代码前,REBOL 解释器会在USER 语境内新增Apple-fanprintGooglefan

这三个单字,并从LIB 语境中将print 定义复制过来(LIB 语境中没有Apple-fan 

Google-fan 的定义)。执行后,Apple-fanGoogle-fan的定义都是代码方块,内容都

[print OS]print OS 被标上红色三角,表示它们都是采用USER 语境(红色的表)

的单字定义。

 

bind Apple-fan Apple

bind Google-fan Google

为了方便解说,我假设上述两个命令行是一起执行的(就像是一个命令行)。

执行上述代码前,REBOL 解释器会在USER 语境内新增bind,并从LIB 语境中将bind 

义复制过来。执行此代码后,Apple-fan内的代码要被绑定到Apple 语境,但Apple 语境

中的单字只有OS,没有print,所以只有OS 被绑定到Apple 语境print 维持原来的绑

定(USER 语境)。同理,Google-fan内的代码只有OS 被绑定到Google 语境print 

持原来的绑定(USER 语境)。

 

code: []

insert code Apple-fan

insert code Google-fan

为了方便解说,我假设上述三个命令行是一起执行的(就像是一个命令行)。

执行这段代码前,REBOL 解释器会在USER 语境内新增code insert,并从LIB 语境中

insert 定义复制过来。执行此代码后,code 内容指向一个新的代码方块,方块内有四个

单字,复制自Apple-fanGoogle-fan。注意区分这里的四个单字分别采用哪些语境。由

Google-fan 的代码较晚插入方块头部(insert 是插入头部的意思),所以第一个OS 

实是来自Google-fan的。

 

code

do code

为了方便解说,我假设上述两个命令行是一起执行的(就像是一个命令行)。

执行这段代码前,REBOL 解释器会在USER 语境内新增do,并从LIB 语境中将do 的定义

复制过来。执行此代码后,屏幕上会依次打印出Google 语境的OS 值("Android")与

Apple 语境的OS 值("iOS")。

 

接续前面的例子,Google 语境与Apple 语境都有OS。这时如果我们直接在交互环境中输入

OS,想取得OS 的值,却得到报错,告诉我们OS 没有值。USER 语境中确实有OS,只是其定

义是特殊值unset(未设),相当于没有值。接着我们把OS 设置为"Windows",以后我们取

得的OS 就会是"Windows"

要如何获取Apple Google 内的OS ?我们可以通过加入路径(path)来实现:在OS 前面

冠上它的来源语境,并用斜杠隔开,写成Apple/OSGoogle/OS

路径不限定两层,可以有多层次。例如,system/options/home就是三层的路径,可以取

得REBOL 主目录。

再来看另一个例子,PI(圆周率)的值原本是3.14159265358979,我们把它改为简单一点

的值3.14。不用担心这个比较精确的值就因此消失了,你改变的只是USER语境中的PI 

制版本,原本的PI 还在LIB 语境中,通过LIB/PI 路径的写法就可以得到原本的值了。

 

写代码时,我们常需要让一些值聚在一起,例如,记录同一个人的信息就放在一起["Tony"

1983-12-21]。为了清楚表达这些数据的意义,我们通常会在前面加上字段名称,变成

[name: "Tony" birthday:1983-12-21]。我们常会把像这样的数据包装成对象(object)。

对象的写法如下所示:

customer1: object [name: "Tony"birthday: 1983-12-21]

customer2: object [name: "John"birthday: 1978-1-15]

这里有两个对象,它们的数据分别被隔开,不用担心"John"会覆盖"Tony",因为它们的

name 是在不同的对象内。

这是不是感觉很像语境?没错! REBOL 其实就是用处理对象的方式来处理语境。语境和对象

在REBOL 语言中是不区分的,作用完全一样。一般来说,语境内放的单字比较多;对象内放

置的单字(字段)比较少。语境内的值不固定,变化很多;对象内的值则相对固定,就像是数

据库的字段一样。语境内函数占大多数,而对象内数据居多。

程序执行的过程会需要经常查询语境,从中找出单字对应的定义,才知道要如何执行。

我们证明过,单字的定义可以来自不同的语境。甚至即使同样的值,真正执行时也可以有不同

的意义(受到该值前面的函数控制),每个值都可能会影响后续值的意义。

REBOL 是Relative Expression Based ObjectLanguage 的缩写,意思就是此语言让你能够根据上

下文(语境)做出不同的表达。同样的一个字,在不同的上下文中可以有不同的定义与效果。

与上下文有关,更容易理解,代码更容易阅读,更简短。

这是一门神奇的语言,威力强大,既神奇又先进。