lua__参考手册docx页内容摘要:
创建一个列表 {f(), nil} f() 被调整为一个结果 被括号括起来的表达式永远被当作一个值。 所以, (f(x,y,z)) 即使 f 返回多个值,这个表达式永远是一个单一值。 ( (f(x,y,z)) 的值是 f 返回的第一个值。 如果 f 不返回值的话,那么它的值就是 nil。 ) 数学运算操作符 Lua 支持常见的数学运算操作符:二元操作 + ( 加法), (减法), * (乘法), / (除法), % (取模),以及 ^ (幂);和一元操作 (取负)。 如果对数字操作,或是可以转换为数字的字符串(参见 167。 ),所有这些操作都依赖它通常的含义。 幂操作可以对任何幂值都正常工作。 比如, x^() 将计算出 x 平方根的倒数。 取模操作被定义为 a % b == a (a/b)*b 这就是说,其结果是商相对负无穷圆整后的余数。 (译注:负数对正数取模的结果为正数) 比较操作符 Lua 中的比较操作符有 == ~= = = 这些操作的结果不是 false 就是 true。 等于操作 (==) 首先比较操作数的类型。 如果类型不同,结果就是 false。 否则,继续比较值。 数字和字符串都用常规的方式比较。 对象 ( table , userdata ,thread ,以及 函数)以引用的形式比较:两个对象只有在它们指向同一个东西时才认为相等。 每次你创建一个新对象(一个 table 或是 userdata , thread 函数),它们都各不相同,即不同于上次创建的东西。 你可以改变 Lua 比较 table 和 userdata 的方式,这需要使用 eq 这个原方法(参见 167。 )。 167。 中提及的转换规则并不作用于比较操作。 所以, 0==0 等于 false,而且 t[0] 和 t[0] 描述的是 table 中不同的域。 操作符 ~= 完全等价于 (==) 操作的反值。 大小比较操作以以下方式进行。 如果参数都是数字,那么就直接做数字比较。 否则,如果参数都是字符串,就用字符串比较的方式进行。 再则, Lua 就试着 调用 lt 或是 le 元方法(参见 167。 )。 逻辑操作符 Lua 中的逻辑操作符有 and, or, 以及 not。 和控制结构(参见 167。 2 .)一样,所有的逻辑操作符把 false 和 nil 都作为假,而其它的一切都当作真。 取反操作 not 总是返回 false 或 true 中的一个。 与操作符 and 在第一个参数为 false 或 nil 时返回这第一个参数;否则, and 返回第二个参数。 或操作符 or 在第一个参数不为 nil 也不为 false 时,返回这第一个参数,否则返回第二个参数。 and 和 or 都遵循短路规则;也就是说,第二个操作数只在需要的时候去求值。 这里有一些例子: 10 or 20 10 10 or error() 10 nil or a a nil and 10 nil false and error() false false and nil false false or nil nil 10 and 20 20 (在这本手册中, 指前面表达式的结果。 ) 连接符 Lua 中字符串的连接操作符写作两个点 (39。 ..39。 )。 如果两个操作数都是字符串或都是数字,连接操作将以 167。 中提到的规则把其转换为字符串。 否则,会取调用元方法 concat (参见 167。 )。 取长度操作符 取长度操作符写作一元操作。 字符串的长度是它的字节数(就是以一个字符一个字节计算的字符串长度)。 table t 的长度被定义成一个整数下标 n。 它满足 t[n] 不是 nil 而 t[n+1] 为 nil;此外,如果 t[1] 为 nil , n 就可能是零。 对于常规的数组,里面从 1 到 n 放着一些非空的值的时候,它的长度就精确的为 n,即最后一个值的下标。 如果数组有一 个 “ 空洞 ” (就是说, nil 值被夹在非空值之间),那么 t 可能是指向任何一个是 nil 值的前一个位置的下标(就是说,任何一个 nil 值都有可能被当成数组的结束)。 优先级 Lua 中操作符的优先级写在下表中,从低到高优先级排序: or and = = ~= == .. + * / % not (unary) ^ 通常,你可以用括号来改变运算次序。 连接操作符 (39。 ..39。 ) 和幂操作 (39。 ^39。 ) 是从右至左的。 其它所有的操作都是从左至右。 Table 构造 table 构造子是一个构造 table 的表达式。 每次构造子被执行,都会构造出一个新的 table。 构造子可以被用来构造一个空的 table,也可以用来构造一个 table 并初始化其中的一些域。 一般的构造子的语法如下 tableconstructor ::= `{180。 [fieldlist] `}180。 fieldlist ::= field {fieldsep field} [fieldsep] field ::= `[180。 exp `]180。 `=180。 exp | Name `=180。 exp | exp fieldsep ::= `,180。 | `。 180。 每个形如 [exp1] = exp2 的域向 table 中增加新的一项,其键值为 exp1 而值为 exp2。 形如 name = exp 的域等价于 [name] = exp。 最后,形如 exp 的域等价于 [i] = exp , 这里的 i 是一个从 1 开始不断增长的数字。 这这个格式中 的其它域不会破坏其记数。 举个例子: a = { [f(1)] = g。 x, y。 x = 1, f(x), [30] = 23。 45 } 等价于 do local t = {} t[f(1)] = g t[1] = x 1st exp t[2] = y 2nd exp = 1 t[x] = 1 t[3] = f(x) 3rd exp t[30] = 23 t[4] = 45 4th exp a = t end 如果表单中最后一个域的形式是 exp ,而且其表达式是一个函数调用或者是一个可变参数,那么这个表达式所有的返回值将连续的进入列表(参见 167。 )。 为了避免这一点,你可以用括号把函数调用(或是可变参数)括起来(参见 167。 )。 初始化域表可以在最后多一个分割符,这样设计可以方便由机器生成代码。 函数调用 Lua 中的函数调用的语法如下: functioncall ::= prefixexp args 函数调用时,第一步, prefixexp 和 args 先被求值。 如果 prefixexp 的值的类型是 function,那么这个函数就被用给出的参数调用。 否则 prefixexp 的元方法 call 就被调用,第一个参数就是 prefixexp 的值,跟下来的是原来的调用参数(参见 167。 )。 这样的形式 functioncall ::= prefixexp `:180。 Name args 可以用来调用 方法。 这是 Lua 支持的一种语法糖。 像 v:name(args) 这个样子,被解释成 (v,args),这里 v 只会被求值一次。 参数的语法如下: args ::= `(180。 [explist1] `)180。 args ::= tableconstructor args ::= String 所有参数的表达式求值都在函数调用之前。 这样的调用形式 f{fields} 是一种语法糖用于表示 f({fields});这里指参数列表是一个单一的新创建出来 的列表。 而这样的形式 f39。 string39。 (或是 fstring 亦或是 f[[string]])也是一种语法糖,用于表示 f(39。 string39。 );这里指参数列表是一个单独的字符串。 因为表达式语法在 Lua 中比较自由,所以你不能在函数调用的 39。 (39。 前换行。 这个限制可以避免语言中的一些歧义。 比如你这样写 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) 返回值被调整为一个 函数定义 函数定义的语法如下: function ::= function funcbody funcbody ::= `(180。 [parlist1] `)180。 block end 另外定义 了一些语法糖简化函数定义的写法: stat ::= function funame funcbody stat ::= local function Name funcbody funame ::= Name {`.180。 Name} [`:180。 Name] 这样的写法: function f () body end 被转换成 f = function () body end 这样的写法: function () body end 被转换成 = 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 [`,180。 `...180。 ] | `...180。 当一个函数被调用,如果函数没有被定义为接收不定长参数,即 在形参列表的末尾注明三个点 (39。 ...39。 ),那么实参列表就会被调整到形参列表的长度,变长参数函数不会调整实参列表;取而代之的是,它将把所有额外的参数放在一起通过变长参数表达式传递给函数,其写法依旧是三个点。 这个表达式的值是一串实参值的列表,看起来就跟一个可以返回多个结果的函数一样。 如果一个变长参数表达式放在另一个表达式中使用,或是放在另一串表达式的中间,那么它的返回值就会被调整为单个值。 若这个表达式放在了一系列表达式的最后一个,就不会做调整了(除非用括号给括了起来)。 我们先做如下定义,然后再来看一个例子 : function f(a, b) end function g(a, b, ...) end。lua__参考手册docx页
阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。
用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。