变量、常量

变量、常量指代码中表示数据的对象,通常使用合法的标志符、字面值(数值、字符串)来表示。

变量

在程序运行过程中,用来存储数据值并且其值能被改变的对象称为变量。
变量的名称用字母、数字、中文字符、下划线等组成的合法标识符来表示


变量名开始字符不能为数字。
变量名包含中文时,中文字符前面不能有字母或数字。
可以使用美元符号($)作为变量名或变量名的第一个字符。

常量名 使用首字符为下划线且长度大于 1 个字节、小于 256 个字节的标识符表示,单个下划线符号仍然表示变量而非常量。


应遵循就近原则(Principle of Proximity):在第一次使用局部变量之前定义该变量,以使代码保持清晰的结构。

1、成员变量

成员变量是属于一个名字空间的成员对象。
变量的默认名字空间为global名字空间,并可以使用namespace改变指定代码块的名字空间。
可以使用self关键字访问当前名字空间。使用..操作符访问global名字空间

//没有用var语句显式声明的变量,默认就是当前名字空间的成员变量

变量 = "字符串:普通变量";
变量 = "变量的值是可以改变的"

..str = 123; //..str等价于 ..global.str


2、局部变量

var声明一个局部变量,作用域为当前语句块,以及被当前语句块所包含的语句块。
var语句声明的局部变量可以指定一个初始值,也可以不指定,建议对所有变量指定初始值。

例如:

var 局部变量;
局部变量 = 123;

var a,b,c = 1,2,3
io.print( a,b,c,局部变量 )

请参考:var赋值语句 函数局部变量


常量

在程序运行过程中,用来存储数据值并且其值不能被改变的对象称为常量,常量赋为非 null 值以后就不能再更改值。


1、字面常量

指以数值、字符串等字面值表示数据的对象。
象123,"abc"这样的值被称之为字面值,被称为字面值是因为它的值就是代码直接描述的值,并且没有名字可以称呼它,只能用它的值来表示。


2、常量

如果常量的值为 null,则可以赋值为非 null 值,之后就就不能再修改值。常量重复赋于相同的数字或字符串等常量值会被忽略(不会报错),修改已赋值常量的值将会抛出错误。

2.1 成员常量

名字空间或表对象的成员名称如果首字符为下划线,并且长度大于 1 个字节并小于 256 个字节,则称为『成员常量』。

成员常量与成员变量一样默认创建于当前名字空间 (self 名字空间 )。

例如:

_const = 123;
_const = 123;//没有修改常量,被忽略
_const = 456;//出错,抛出异常:不能修改只读成员
要特别注意,不仅仅是可以使用合法标识符表示成员常量,直接使用字符串表示成员名字时也表示常量,例如:
self["_ (不是合法标识符)"] = 1;
self["_ (不是合法标识符)"] = 1234;//报错,不能修改常量

在对象元表中指定元属性_readonly = false 可禁用读成员保护,
如果元表中不设置_readonly 则默认启用只读成员保护(所有名字以下划线开头的禁止修改非null值)。

如果元表中设置 _readonly 为任何非null值都会被强制转换为 false,
该值一旦设置以后即不可修改,如果希望启用只读成员保护,唯一的方法就是不设置该属性。

global对象无论元属性_readonly怎么设置都会被忽略,只读成员保护总是启用状态。


2.2 全局常量

全局常量类似于成员常量,区别是必须大写、并且位于globle根名字空间。

实际上使用全局对象是不好的习惯,更好的方法是将它们放入适当的名字空间。
不要介意多打几个字多写几个名字空间前缀,理解了全局对象会不知不觉增加程序的复杂度,意谓着你已经成为了一名有经验的程序员。


将全局常量改为字面常量并加上注释是一个不错的优化方案,aardio 提供相应的工具。
这种优化技术被用于libs\\win\#DEFINE.aardio(这不是一个库,放在库目录下仅仅是为了让扫描常量声明到智能提示数据库),效果如下:

常量优化

2.3 保留全局常量
在合法变量名前加上 :: 前缀,可将其转换为保留全局常量。
再次使用保留全局常量名时可以省略 :: 前缀。

保留全局常量一旦赋为非 null 值后即不可修改,例如:


::Kernel32 := raw.loadDll("Kernel32.dll");

:: 的作用域是根据代码的载入、编译顺序向下向后生效的。
因为代码载入与编译顺序有不确定性,所以除了 aardio 预定义的保留全局常量,
一般不建议省略 :: 前缀。

保留全局常量会同时被提升到语法关键字级别,不能再作为普通变量名使用。

全局常量不能作为普通标识符使用,
所有全局常量不能与普通变量、局部变量同名,且无法被覆盖。

例如:
var eval
var _GLOBAL;  
都会报语法错误。

所以请避免滥用全局常量。
尤其不要定义极少字符、甚至是单个小写字符的保留全局常量。

应减少使用保留全局常量,以避免增加大量不必要的语法保留字。
aardio 标准库只将少量的系统 DLL 模块、系统 API 函数定义为保留全局常量。



所有全局常量需要遵守以下使用规则:

1、全局常量名首字母大写(以区别普通变量 )。
aardio 默认定义了少量保留全局常量函数名 - 这些保留函数全部小写首字母,但在 aardio 编辑器中显示为蓝色高亮状态。保留函数属于 global 名字空间,并在所有名字空间下可以直接使用。

以下为 aardio 提供的保留函数列表,关于这些保留函数的具体用法,请参考《库函数文档》或 aardio 编辑器的函数提示。

type  关键函数,用于获取对象的数据类型
eval  运行aardio代码,并计算表达式的值
assert  断言函数
assertf  反断言函数
error  抛出异常
tostring  用于转换参数为字符串
topointer  用于转换参数为指针
tonumber  用于转换参数为数值
loadcode  用于加载代码
loadcodex  用于加载执行代码
dumpcode  用于编译代码
rget  用于选择返回值
collectgarbage  用于回收内存
invoke  用于调用函数
call  用于调用函数
callex  用于调用函数
sleep  用于休眠
execute  用于调用系统命令
setlocale  用于区域设置
setprivilege  用于指定进程权限


2、全局常量赋于非 null 值以后不能再更改值。
常量仅能初始化赋值一次,对于相同的字符串或数值 —— 重复赋于相同的值会被自动忽略。如果是其他值则不能保证每次创建的值是相同的,为避免无意中修改常量值导致异常,可使用 := 操作符赋值。

例如:

::GlobalFunc := function() {

};

上面的代码等效于:

::GlobalFunc = ::GlobalFunc or function() {

};