2.2 lua 基础数据类型
lua 是一门极其精简的语言,内置类型只要nil
,boolean
,number
等三种基本类型,以及string
,table
等二种组合类型。没有C/C++ 等语言中的class
、struct
等复杂类型,这些类型可以通过table
来实现。同时,不同于其他语言(如C/C++和java),function
在lua中也作为一个一级类型。
nil
nil
是一种类型,Lua 将 nil
用于表示“无效值”。
- 一个变量在第一次赋值前的默认值是
nil
- 将
nil
赋予给一个全局变量就等同于删除它. - openresty 中提供了另一种表示空值的类型
ngx.null
.
nil
在lua中有其特殊意义,如果一个变量被设置为nil
,就等于说该变量未定义,与无穷无尽的其他未定义的变量一样。那么,如果把redis查询为空的结果设置为nil
,就无法把”查询为空”和“未定义”区分开来了,例如在一个table中,一个key对应一个value,如果将该value设置为nil
,则相当让key凭空消失,这显然是不合理的。所以必须用一个userdata类型的独特的值来表示这种查询为空,但又不等同于未定义的变量,例如ngx.null
。同样的情况想必在sql的lua模块中也会出现,用来处理记录中键值查询为空的情况。
lua中神奇的nil
了。nil
是一种类型,该类型只有一个值,这个值就是nil
。该值的作用只有一个,表示一个变量不存在。跟C\C++等常规语言不同,”不存在“跟空、0完全是两个概念。在C语言中,一个字符串如果为空,那么它就只有一个为0
的\nul
结束符,如果对齐进行逻辑判断,则是假。但lua中,只要一个变量不是nil
类型或者是boolean类型中的false
,则对它进行逻辑判断,结果是真,即使该值是一个数字0,或者是一个空字符串。
boolean
布尔类型,可选值 true/false;Lua 中 nil 和 false 为“假”,其它所有值均为“真”。比如 0 和空字符串就是“真”;C 或者 Perl 程序员或许会对此感到惊讶。
number
Number 类型用于表示实数,和 C/C++ 里面的 double
类型很类似。可以使用数学函数math.floor
( 向下取整) 和 math.ceil
( 向上取整) 进行取整操作。
一般地,Lua 的 number 类型就是用双精度浮点数来实现的。值得一提的是,LuaJIT 支持所谓的“dual-number”( 双数) 模式,即 LuaJIT 会根据上下文用整型来存储整数,而用双精度浮点数来存放浮点数。另外,LuaJIT 还支持“长长整型”的大整数( 在 x86_64 体系结构上则是 64 位整数) 。例如
1 | print(9223372036854775807LL - 1) |
string
Lua 中有三种方式表示字符串:
- 使用一对匹配的单引号。例:’hello’。
- 使用一对匹配的双引号。例:”hello”。
- 字符串还可以用一种长括号( 即[[ ]]) 括起来的方式定义。我们把两个正的方括号( 即[[)间插入 n 个等号定义为第 n 级正长括号。就是说,0 级正的长括号写作 [[ ,一级正的长括号写作 [=[,如此等等。反的长括号也作类似定义;举个例子,4 级反的长括号写作]====]。一个长字符串可以由任何一级的正的长括号开始,而由第一个碰到的同级反的长括号结束。整个词法分析过程将不受分行限制,不处理任何转义符,并且忽略掉任何不同级别的长括号。这种方式描述的字符串可以包含任何东西,当然本级别的反长括号除外。例:[[abc\nbc]],里面的 “\n” 不会被转义。
特别注意:Lua 的字符串是不可改变的值,不能像在 c 语言中那样直接修改字符串的某个字符,而是根据修改要求来创建一个新的字符串。Lua 也不能通过下标来访问字符串的某个字符。
1 | local str1 = 'hello world' |
特别注意: 从上面实例str5
和str6
可以看出'
和"
在lua中作用是一致的,二者中的\n
这类转义字符都会被转义,这一点要区别一下shell中'
和"
。
在 Lua 实现中,Lua 字符串一般都会经历一个“内化”( intern) 的过程,即两个完全一样的Lua 字符串在 Lua 虚拟机中只会存储一份。每一个 Lua 字符串在创建时都会插入到 Lua 虚拟机内部的一个全局的哈希表中。 这意味着
- 创建相同的 Lua 字符串并不会引入新的动态内存分配操作,所以相对便宜( 但仍有全局哈希表查询的开销。
- 内容相同的 Lua 字符串不会占用多份存储空间。
- 已经创建好的 Lua 字符串之间进行相等性比较时是 O(1) 时间度的开销,而不是通常见到的 O(n),比较索引就可以了。
table
Table 类型实现了一种抽象的“关联数组”。“关联数组”是一种具有特殊索引方式的数组,索引通常是字符串( string) 或者 number 类型,但也可以是除 nil 以外的任意类型的值。
1 | local corp = { |
在内部实现上,table 通常实现为一个哈希表、一个数组、或者两者的混合。具体的实现为何种形式,动态依赖于具体的 table 的键分布特点。
function
在 Lua 中,函数:
- 也是一种数据类型,
- 函数可以存储在变量中,
- 可以通过参数传递给其他函数,
- 还可以作为其他函数的返回值
1 | local function foo() |
有名函数的定义可以理解为是匿名函数对变量的赋值。
1 | function foo() |
可以写成如下形式:
1 | foo = function () |
类似地,
1 | local function foo() |
等价于
1 | local foo = function () |