数据类型及运算
作为一款无类型的编程语言,变量赋值即完成声明,变量在赋值时会自动根据值的属性自动切换变量数据类型.使用者本无须关心数据类型,但是在做变量运算时,数据类型对变量运算的结果会产生深远的影响,如字符串只有加法等,因此有必要对变量类型进行了解.
变量在使用前必须赋值,否则会报标志未定义的错误
数据类型
EQ语言的数据变量类型分为以下几种:
- string 字符串 "eq"
- num 数字 1,1.0,-12
- bool 布尔 true,false
- regexp 正则 '[0-9]'
- complex 复数 2i,1+3i
- matrix 矩阵 [1,true;-12,2i;true]
- null null null
- undefine 未定义 undefine
- function 函数 core.print
- native
矩阵类型使用(,)区分列,使用(;)区分行,支持矩阵的基本四则运算,后续将会支持更多运算.
值得注意的是矩阵定义
/// good
a=[2,3;4];
b=[2,a;a,4];
/// bad
b=[2,[2,3;4];[2,3;4],4];
native类型只能被变量存储和使用,无法被打印和读取
使用函数instance(args)可以查看当前变量数据类型,如函数类型可以打印所在模块及函数签名core.print
使用未定义的变量会直接报错,让未定义的变量继续运行是一件比较可怕的事情.undefine只存在函数参数上的使用,为实现函数多态性.
##作用域
EQ具有顶层语句执行能力,也就是说语句执行的上下文环境会随着函数跳转等进行动态切换.
局部变量
EQ语言定义凡是使用大括号包裹的内部环境属于局部环境,即大括号内部定义的变量无法在该大括号外部使用,但嵌套大括号里层可以使用外层的环境.
全局变量
主模块顶层语句定义的变量均为全局变量,访问必须使用$符号.
非主模块的全局变量只能由该模块的load函数定义(load函数定义见第六章 模块).访问使用模块名.变量名(如a.b:访问a模块中的全局变量b).
私有变量和函数
以下划线开头的全局变量和函数属于所在模块的私有属性,无法被其它模块访问[todo].
if,switch case,for以及while的表达式是不在大括号之内的,其条件表达式所处的环境因具体情况而不同,一般是该语句所处的当前上下文环境,语句内部定义的内容无法被访问.
函数
EQ语言原本想设计为纯函数式语言,但是为了能更加方便使用,降低了函数在主模块中的地位,但是在被引入的模块中,函数处于头等地位,因为被引入的模块中的非函数语句是无法被执行的.一个标准函数的定义及调用如下:
function a(a,b){
print(a,b);
}
a(1,2);
函数被调用与函数所处的位置无关,只要函数在所属模块内被定义即可.函数最终返回没有return语句的时候,默认返回值为null.函数调用时传递的参数与函数定义的参数从左往右一一赋值,直到一方的参数结束,因此上述a函数的调用也可以使用a(1)[b的类型为undefined]或者a(1,2,3),多余的参数不会被定义或者被执行.
模块
模块是一个比较重要的概念,如果没有模块,写出来的代码将混在一起,很难阅读与维护,经常会将实现同一功能的不同函数写在同一个模块里给其它模块导入使用.文件名即为模块原始名.
导入语句如下
import eq.core;
core.print("hello world");
///
import eq.core as a;
a.print("hello world");
以上便导入了core模块,as关键词将core模块在当前模块中重命名为a,则该模块被使用使用其限定符由core变为a.
core模块
core模块作为EQ的核心模块是各个模块都默认导入的,无须再重复导入,使用时也无须带有core限定符.如果在模块中声明了与core模块中同名函数,则优先调用本模块函数,除非函数带有模块限定符.
模块加载
所有的模块都是懒加载型的,即模块内的内容被首次使用时才会去进行编译加载,被首次加载的模块会执行其内部的load函数(没有则跳过),此时执行load函数,会将函数内部定义的变量作为该模块的全局变量而一直全局可见,直到模块的生命周期结束,后续如果手动执行该函数将变成普通函数执行模式,不对全局变量产生影响.
模块导入
所有的模块导入都由import关键词完成,可以由关键词as进行重命名使用.模块主要分为三大类加载,每种类别加载路径不一致.
形如import eq.core;这种由eq.限定的都属于EQ语言内置模块,无须外部文件加载.
形如import pub.a;这种由pub.限定的模块将会在项目根目录下项目配置文件eq.json中pub属性设定的路径中搜索(优先)以及编译器设定的公共模块路径下搜索,根据搜索顺序,搜到即编译加载.
其它导入形式如import a.b;将以项目根目录为相对路径起点进行模块匹配,该例子为项目根目录下子目录a中的b文件模块.