lua的参考手册

Lua的参考手册《1》

管理提醒:
本帖被 lua china 从 lua新手入门 移动到本区(2008-12-01)

跟索引一样, table 每个域中的值也可以是任何类型(除 nil外)。特别的,因为函数本身也是值,所以 table 的域中也可以放函数。这样 table 中就可以有一些 methods 了 (参见see §2.5.9)。

table, function ,thread ,和 (full) userdata 这些类型的值是所谓的对象:变量本身并不会真正的存放它们的值,而只是放了一个对对象的引用。赋值,参数传递,函数返回,都是对这些对象的引用进行操作;这些操作不会做暗地里做任何性质的拷贝。

库函数 type 可以返回一个描述给定值的类型的字符串。

2.2.1 - 强制转换

Lua 提供运行时字符串到数字的自动转换。任何对字符串的数学运算操作都会尝试用一般的转换规则把这个字符串转换成一个数字。相反,无论何时,一个数字需要作为字符串来使用时,数字都会以合理的格式转换为字符串。需要完全控制数字怎样转换为

因为表达式语法在 Lua 中比较自由,所以你不能在函数调用的 '(' 前换行。这个限制可以避免语言中的一些歧义。比如你这样写

a = f

(g).x(a)

Lua 将把它当作一个单一语句段, a = f(g).x(a) 。因此,如果你真的想作为成两个语句段,你必须在它们之间写上一个分号。如果你真的想调用 f,你必须从 (g) 前移去换行。

这样一种调用形式:return functioncall 将触发一个尾调用。 Lua 实现了适当的尾部调用(或是适当的尾递归):在尾调用中,被调用的函数重用调用它的函数的堆栈项。因此,对于程序执行的嵌套尾调用的层数是没有限制的。然而,尾调用将删除调用它的函数的任何调试信息。注意,尾调用只发生在特定的语法下,这时, return 只有单一函数调用作为参数;这种语法使得调用函数的结果可以精确返回。因此,下面这些例子都不是尾调用:

return (f(x)) -- 返回值被调整为一个

return 2 * f(x)

return x, f(x) -- 最加若干返回值

f(x); return -- 无返回值

return x or f(x) -- 返回值被调整为一个

2.5.9 - 函数定义

函数定义的语法如下:

function ::= function funcbody

funcbody ::= `(´ [parlist1] `)´ block end

另外定义了一些语法糖简化函数定义的写法:

stat ::= function funcname funcbody

stat ::= local function Name funcbody

funcname ::= Name {`.´ Name} [`:´ Name]

这样的写法:

function f () body end

被转换成

f = function () body end

这样的写法:

function t.a.b.c.f () body end

被转换成

t.a.b.c.f = function () body end

这样的写法:

local function f () body end

被转换成

local f; f = function () body end

注意,并不是转换成

local f = function () body end

(这个差别只在函数体内需要引用 f 时才有。)

一个函数定义是一个可执行的表达式,执行结果是一个类型为 function 的值。当 Lua 预编译一个 chunk 的时候, chunk 作为一个函数,整个函数体也就被预编译了。那么,无论何时 Lua 执行了函数定义,这个函数本身就被实例化了(或者说是关闭了)。这个函数的实例(或者说是 closure(闭包))是表达式的最终值。相同函数的不同实例有可能引用不同的外部局部变量,也可能拥有不同的环境表。

形参(函数定义需要的参数)是一些由实参(实际传入参数)的值初始化的局部变量:

parlist1 ::= namelist [`,´ `...´] | `...´

当一个函数被调用,如果函数没有被定义为接收不定长参数,即在形参列表的末尾注明三个点 ('...'),那么实参列表就会被调整到形参列表的长度,变长参数函数不会调整实参列表;取而代之的是,它将把所有额外的参数放在一起通过变长参数表达式传递给函数,其写法依旧是三个点。这个表达式的值是一串实参值的列表,看起来就跟一个可以返回多个结果的函数一样。如果一个变长参数表达式放在另一个表达式中使用,或是放在另一串表达式的中间,那么它的返回值就会被调整为单个值。若这个表达式放在了一系列表达式的最后一个,就不会做调整了(除非用括号给括了起来)。

我们先做如下定义,然后再来看一个例子:

function f(a, b) end

function g(a, b, ...) end

function r() return 1,2,3 end

下面看看实参到形参数以及可变长参数的映射关系:

CALL PARAMETERS

f(3) a=3, b=nil

f(3, 4) a=3, b=4

f(3, 4, 5) a=3, b=4

f(r(), 10) a=1, b=10

f(r()) a=1, b=2

g(3) a=3, b=nil, ... --> (nothing)

g(3, 4) a=3, b=4, ... --> (nothing)

g(3, 4, 5, 8) a=3, b=4, ... --> 5 8

g(5, r()) a=5, b=1, ... --> 2 3

结果由 return 来返回(参见 §2.4.4)。如果执行到函数末尾依旧没有遇到任何 return 语句,函数就不会返回任何结果。

冒号语法可以用来定义方法,就是说,函数可以有一个隐式的形参 self。因此,如下写法:

function t.a.b.c:f (params) body end

是这样一种写法的语法糖:

t.a.b.c.f = function (self, params) body end

2.6 - 可视规则

Lua 是一个有词法作用范围的语言。变量的作用范围开始于声明它们之后的第一个语句段,结束于包含这个声明的最内层语句块的结束点。看下面这些例子:

x = 10 -- 全局变量

do -- 新的语句块

local x = x -- 新的一个 'x', 它的值现在是 10

print(x) --> 10

x = x+1

do -- 另一个语句块

local x = x+1 -- 又一个 'x'

print(x) --> 12

end

print(x) --> 11

end

print(x) --> 10 (取到的是全局的那一个)

注意这里,类似 local x = x 这样的声明,新的 x 正在被声明,但是还没有进入它的作用范围,所以第二个 x 指向的是外面一层的变量。

因为有这样一个词法作用范围的规则,所以可以在函数内部自由的定义局部变量并使用它们。当一个局部变量被更内层的函数中使用的时候,它被内层函数称作 upvalue(上值),或是 外部局部变量。

注意,每次执行到一个 local 语句都会定义出一个新的局部变量。看看这样一个例子:

a = {}

local x = 20

for i=1,10 do

local y = 0

a = function () y=y+1; return x+y end

end

这个循环创建了十个 closure(这指十个匿名函数的实例)。这些 closure 中的每一个都使用了不同的 y 变量,而它们又共享了同一份 x。

--------------------------------------------------------------------------------

lua_gettop

int lua_gettop (lua_State *L);

返回栈顶元素的索引。因为索引是从 1 开始编号的,所以这个结果等于堆栈上的元素个数(因此返回 0 表示堆栈为空)。

--------------------------------------------------------------------------------

lua_insert

void lua_insert (lua_State *L, int index);

把栈顶元素插入指定的有效索引处,并依次移动这个索引之上的元素。不要用伪索引来调用这个函数,因为伪索引不是真正指向堆栈上的位置。

--------------------------------------------------------------------------------

lua_Integer

typedef ptrdiff_t lua_Integer;

这个类型被用于 Lua API 接收整数值。

缺省时这个被定义为 ptrdiff_t ,这个东西通常是机器能处理的最大整数类型。

--------------------------------------------------------------------------------