2.2 - 值与类型
Lua 是一种 动态类型语言。这意味着变量没有类型,只有值才有类型。语言中不存在类型定义。而所有的值本身携带它们自己的类型信息。
Lua 中的所有值都是一致 (first-class) 的。这意味着所有的值都可以被放在变量里,当作参数传递到另一个函数中,并被函数作为结果返回。
Lua 中有八种基本类型: nil, boolean, number, string, function, userdata,thread, and table.Nil 类型只有一种值 nil ,它的主要用途用于标表识和别的任何值的差异;通常,当需要描述一个无意义的值时会用到它。Boolean 类型只有两种值:false 和 true。nil 和false 都能导致条件为假;而另外所有的值都被当作真。 Number 表示实数(双精度浮点数)。(编译一个其它内部数字类型的 Lua 解释器是件很容易的事;比如把内部数字类型改作单精度浮点数或长整型。参见文件luaconf.h 。)String 表示一串字符的数组。 Lua 是 8-bit clean 的:字符串可以包含任何 8 位字符,包括零结束符 ('\0') (参见 §2.1)。
Lua 可以调用(和处理)用 Lua 写的函数以及用 C 写的函数(参见 §2.5.8).
userdata 类型用来将任意 C 数据保存在 Lua 变量中。这个类型相当于一块原生的内存,除了赋值和相同性判断,Lua 没有为之预定义任何操作。然而,通过使用metatable (元表),程序员可以为 userdata 自定义一组操作(参见 §2.8)。 userdata 不能在 Lua 中创建出来,也不能在 Lua 中修改。这样的操作只能通过 C API。这一点保证了宿主程序完全掌管其中的数据。
thread 类型用来区别独立的执行线程,它被用来实现 coroutine (协同例程)(参见 §2.11)。不要把 Lua 线程跟操作系统的线程搞混。 Lua 可以在所有的系统上提供对 coroutine 的支持,即使系统并不支持线程。
table 类型实现了一个关联数组。也就是说,数组可以用任何东西(除了nil)做索引,而不限于数字。 table 可以以不同类型的值构成;它可以包含所有的类型的值(除nil 外)。table 是 lua 中唯一的一种数据结构;它可以用来描述原始的数组、符号表、集合、记录、图、树、等等。用于表述记录时,lua 使用域名作为索引。语言本身采用一种语法糖,支持以 a.name 的形式表示 a["name"]。有很多形式用于在 lua 中创建一个 table (参见 §2.5.7)。
跟索引一样, table 每个域中的值也可以是任何类型(除 nil外)。特别的,因为函数本身也是值,所以 table 的域中也可以放函数。这样 table 中就可以有一些methods 了 (参见see§2.5.9)。
table, function ,thread,和 (full) userdata 这些类型的值是所谓的对象:变量本身并不会真正的存放它们的值,而只是放了一个对对象的引用。赋值,参数传递,函数返回,都是对这些对象的引用进行操作;这些操作不会做暗地里做任何性质的拷贝。
库函数 type可以返回一个描述给定值的类型的字符串。
2.2.1 - 强制转换
Lua 提供运行时字符串到数字的自动转换。任何对字符串的数学运算操作都会尝试用一般的转换规则把这个字符串转换成一个数字。相反,无论何时,一个数字需要作为字符串来使用时,数字都会以合理的格式转换为字符串。需要完全控制数字怎样转换为字符串,可以使用字符串库中的 format 函数(参见string.format)。
2.3 - 变量
写上变量的地方意味着当以其保存的值来替代之。 Lua 中有三类变量:全局变量,局部变量,还有 table 的域。
一个单一的名字可以表示一个全局变量,也可以表示一个局部变量(或者是一个函数的参数,这是一种特殊形式的局部变量):
var ::= Name
Name 就是 §2.1 中所定义的标识符。
任何变量都被假定为全局变量,除非显式的以 local 修饰定义 (参见 §2.4.7)。局部变量有其作用范围:局部变量可以被定义在它作用范围中的函数自由使用(参见§2.6)。
在变量的首次赋值之前,变量的值均为 nil。
方括号被用来对 table 作索引:
var ::=prefixexp `[´ exp `]´
对全局变量以及 table 域之访问的含义可以通过 metatable 来改变。以取一个变量下标指向的量 t[i] 等价于调用 gettable_event(t,i)。(参见§2.8 ,有一份完整的关于 gettable_event 函数的说明。这个函数并没有在 lua 中定义出来,也不能在 lua 中调用。这里我们把它列出来只是方便说明。)
var.Name 这种语法只是一个语法糖,用来表示var["Name"]:
var ::=prefixexp `.´ Name
所有的全局变量都是放在一个特定 lua table 的诸个域中,这个特定的 table 叫作 environment (环境)table 或者简称为环境 (参见 §2.9)。每个函数都有对一个环境的引用,所以一个函数中可见的所有全局变量都放在这个函数所引用的环境表(environment table)中。当一个函数被创建出来,它会从创建它的函数中继承其环境,你可以调用getfenv取得其环境。如果想改变环境,可以调用 setfenv。(对于 C 函数,你只能通过 debug 库来改变其环境;参见 §5.9)。
对一个全局变量 x 的访问等价于 _env.x,而这又可以等价于
gettable_event(_env, "x")
这里,_env 是当前运行的函数的环境。(函数 gettable_event 的完整说明参见§2.8。这个函数并没有在 lua 中定义出来,也不能调用。当然,_env 这个变量也同样没有在 Lua 中定义出来。我们在这里使用它们,仅仅只是方便解释而已。)