语境与单字
当我们输入一段代码时,REBOL 解释器怎么知道如何执行这段代码?
其实REBOL 解释器一启动,就预先准备好LIB 语境。语境(context)是一张表,把单字对应
到它的定义。这些REBOL 解释器预先定义在LIB 语境中的单字,我称为REBOL 内置单字,
都是一些常用单字。单字的定义可能是程序(函数)或者一般的值(例如整数)。
当REBOL 解释器看到一个单字,就会去LIB 语境中查询,得知如何处理。以power 来说,
REBOL 会从这个语境中找到它的定义,知道这个函数必须计算幂(以及如何计算幂),且需
要两个参数,分别是底数与指数。
有些单字的定义是程序,这样的程序我们称为函数。有些则不是程序,而是静态的值,例如
pi(圆周率)就被定义为3.14159265358979。有些单字的定义是完全一样的,例如q 与
quit。执行程序时,有些单字不会影响其他值(也就是不需要参数),例如what-dir、LS、
pi。有些单字会影响后面的几个值(也就是需要参数),例如do、print。有些单字会影响
一前一后的值(也就是参数必须一个摆在前面,一个摆在后面),例如+ 与/。
如果我们想知道LIB 中定义了多少个单字,可以通过length?LIB 来查询。如果想知道LIB
语境定义了哪些单字,可以在交互环境下输入? LIB 命令行来看看它内部的定义。仔细看看,
有一个单字叫做red,它的定义是255.0.0。如果单字太多,我们无法看到全部的单字定义,
可以考虑采用第2 章介绍的echo 函数,将结果输出到一个文件中,再慢慢研究。
如果只想看看有哪些单字,不想知道单字的定义,则可以通过words-of函数,来取得LIB
语境内的所有单字,但依然会因为返回值的数据量太大,只能看到一部分。这时我们可以通过
foreach 循环的方式,将单字一一打印出来。如果你不懂foreach的用法,先不用担心,第
3 篇会详细介绍。
如果我们改变LIB 语境中已有单字的定义,会如何?red 的值原本是255.0.0(鲜红),我
将red 设置为200.0.0(稍微暗一点的红)。再去观察LIB,却发现我的设置没有效果。怎么
会这样?是不是我的设置没有被记录下来。我在命令行中输入red,得到的值确实是新的值。
我怀疑有另一个语境的存在。所有的定义更改只会影响这神秘的语境,而不会影响LIB 语境。
接着做实验,我先确定LIB 中没有my-name,然后将my-name设置为"Jerry",再到LIB
中寻找,竟然看不到my-name的存在。
上面两个实验之后,我推理出:应该有另一个语境,专门用来记录用户代码执行过程的单字定
义变化。
没错,确实存在这样的语境,它就叫做USER 语境!
USER 语境与LIB 语境之间的分工很明确:
•• LIB 语境提供各种常用的单字定义,方便我们写代码时采用。
•• USER 语境用来记录用户代码执行过程中发生的变化。
通过self 就可以访问USER 语境。先通过? self 看看USER 语境有哪些单字,以及这些
单字的值是多少。我们发现,之前修改的red 以及新增的my-name原来都在这里。
这时突发奇想,如果我把某个REBOL 内置单字(比方说print)改掉其定义,会如何?通
过实验我们发现,我们修改的是USER 语境内的版本,而不是LIB 内的版本。
经过上面的实验与观察,USER 语境中并没有LIB 中所有的单字,只有我们用到的单字。每次
我们输入一行代码,新的单字就会被加进表中。
总而言之,代码在执行前,系统会把代码中所有的单字找出来,然后加到USER 表中。对于
USER 中本来就存在的单字,不受影响。新加入的单字,会试图从LIB 中取得定义,再复制
到USER 语境中。如此一来,我们的代码在执行时,只需要用到一个语境:USER 语境。不过
REBOL 解释器会自动帮我们处理这里所说的一切,所以我们不用为这些麻烦事担心。
总的来说,在代码切割完后,执行代码之前,REBOL 解释器有一些准备工作要进行。
1. 先把代码中使用到的新单字加入USER 语境中,这些新单字的定义都是特殊值unset,
表示尚未设定。
2. 到LIB 语境中搜索这些新单字的定义,把这些定义复制给USER 语境中对应的单字。
做完了上面的准备工作,就可以开始执行代码了。通过上面的准备工作,执行时代码只需要参
考USER 语境即可,不需要参考LIB 语境。
本文节选自《编程ING:人人都能学会程序设计》一书
蔡学镛 著
电子工业出版社出版
图书详细信息:http://blog.youkuaiyun.com/broadview2006/article/details/7768124