语境
到这里,你已经掌握了青语言编程所需要的基础知识了,可以编写一些青语言代码了。
如果你希望进一步了解青语言,那么你还需要深入了解青语言中语境的概念。语境这个词在之前的文档中我们已经几次提到了,现在终于是时候来了解它了。
文档一开始的时候,我们说过青语言中数据的存储是通过和变量名进行绑定来实现的,那么这样的绑定关系是由谁来记录的呢,答案就是这一节的主角——语境
语境是青语言中十分重要的概念,语境无处不在,整个青语言程序都运行在语境中。
青语言中的语境可以理解为就是一张表,一张记录了变量以及函数的绑定关系的表,例如,当我们执行以下赋值语句时,就会在语境中添加记录:
#甲 = 1
#乙 : 2
那么此时语境中的情况大概是这样的:

当然,这这是最简单的情况,事实上语境是稍微复杂一些的结构。之前我们说过,我们通过函数实现模块化,那么我们就不希望函数内部的数据被外部篡改,所以我们不能简单的把所有的变量、函数全都记录到同一张表里。
事实上,青语言中的语境采用的是一种链式的结构,语境间存在上下级的关系,每个语境会记录它上一层的语境。
当青语言解释器启动时,解释器会自动为我们创建一个库语境和一个用户语境,它们的结构如下图所示:

库语境位于青语言语境链的最顶端,我们使用的原生函数都是绑定在这个语境里,由于我们不希望原生函数被破坏,所以这是一个十分特殊的语境,其中的绑定记录只能读取,不能修改。
用户语境位于库语境之下,并且记录了它的上级是库语境。一开始,用户语境是完全空的,我们的程序就运行在用户语境中。
假设我们现在输入代码@显示,会输出对应的元素函数的描述

这说明我们获取到了@显示的信息。
刚才我们说了,我们的程序时运行在用户语境中,但是用户语境明明是空的,所以这时候解释器是如何获取@显示的信息呢?

解释器首先会在当前语境(此时是用户语境)中查找,发现不存在对应的记录,那么就会沿着语境链向上,到上一层语境中查找,如果上一层还没有,就继续向上。如果最终来到库语境仍未能找到,此时已经没有上层语境了,那么就返回空,表示不存在。
在程序运行过程中,还会产生许多语境,有可能存在非常长的语境链,但无论语境链多长,其查询绑定记录的方式都是逐级向上查找。在向上查找的过程中,一旦在某个语境中找到相应的记录,就立即返回记录的值,停止查找。

上面我们介绍了在语境中查找绑定的值的方式,那赋值又是怎样进行的呢。
变量赋值的文档中我们介绍过,赋值的方式有2种,分别用=号和:来实现,并且2者的效果不一样,差异就在于如何在语境链中执行绑定。
首先我们来看比较简单的:方式,这种方式会直接在当前语境中执行绑定。

假设我们在语境N中执行:赋值,那么就直接再语境N中执行绑定。
接下来我们来看一下=方式是如何执行的

使用=的方式比较复杂,除了当前语境外,还需要确定上级语境是否存在对应的绑定记录,所以会向上查找,如果中途发现某个语境中存在绑定记录,那么就修改这个绑定记录。如果一直找不到,那么最终到底用户语境时就会停下,然后在用户语境中执行绑定。
因为不允许修改库语境,所以这里我们最多到达用户语境。除库语境外,用户语境是所有语境的上级,所以这里绑定的值可以被所有的子语境访问到,所以这里的变量可以理解为全局变量。
但是,全局变量并不是一定会被访问到,例如:

所以,在编写代码的过程中,需要明确自己访问的变量所处的语境。
虽然语境的结构可能会比较复杂,但我们在使用时记住以下规则即可处理绝大部分的情况。
什么情况下会创建语境?
从代码上看,基本上语境和大括号 { } 是一一对应的关系,但如果和尝试语句例外。 所以,当你看到代码中的大括号 { }时,通常就会创建一个语境,而且这个新语境的上级语境就是创建它时所处的语境。
当 #序:1,#序 小于等于 10,#序 加等 1 { ;这里大括号会创建语境
@显示、#序
}
@双倍 = @【#甲】{ ;这里大括号会创建语境
#函数内的局部变量 : 真
#甲 * 2
}
#对象 = { ;这里大括号会创建语境
#甲: 1,
@方法:@【】{
@显示、“这是对象里的方法”
}
}
上面的循环语句、函数和对象中,大括号都会创建语境,如果你不希望外部访问到它们内部的数据,那么就使用:的方式把变量定义到新创建的语境中。
注意,当语句中如果存在定义循环控制变量的子句,虽然这个子句在大括号外面,但它也会到大括号内执行。
在函数中我们希望定义不被外界访问到的局部变量时,只需要在这个变量第一次出现的时候使用:实现定义,之后的赋值操作都可以使用=。
对象本身其实就是一个语境,所以我们之前提到过,对象内部属性的定义都应该使用:方式来实现。除了属性外,对象内部还可以定义函数,通常我们把对象内的函数称为——方法。无论属性还是方法,如果是希望定义在对象内,那么就应该使用:方式,如果使用的是=方式,那么在创建对象的过程中,不会定义在对象内,并且可能会对对象外部造成影响。
最后再次提醒,如果和尝试语句是例外情况,不会创建语境。