Lua4.0 参考手册(三)4.5

(接上篇)
-------------------
4.5 表达式
-------------------
---------
4.5.1 基本表达式
---------
Lua 中基本表达式是:
    exp ::= `(‘ exp `)‘
    exp ::= nil
    exp ::= number
    exp ::= literal
    exp ::= var
    exp ::= upvalue
    exp ::= function
    exp ::= functioncall
    exp ::= tableconstructor
数值(数值常量)和字符串常量在 4.1 节解释过了。变量在 4.4.2 节解释过了。upvalue 在 4.6 节解释。函数定义在 4.5.9 节解释。函数调用在 4.5.8 节解释。表的构造函数在 4.5.7 节解释。

一个全局变量 x 的调用等价于调用 getglobal("x"),一个下标变量 t[i] 等价于 gettable_event(t,i) 。这些函数的解释参见 4.8 节(getglobal 在基础的库中,gettable_event 仅用于解释目的)。

非终结的 exp1 被用来指示一个表达式的返回值必须被调整为一个值:
    exp1 ::= exp

---------
4.5.2 算术运算符
---------
Lua 支持常见的算术运算符。这些运算符是二元操作符 +(加), -(减), *(乘), /(除) 和 ^(幂),一元操作符 -(负)。如果操作数是数值,或者是可以转化为数值的字符串(根据 4.2 节中给出的规则),所有的操作(除了幂操作)具有通常意义。否则,一个适用的标签函数(参见 4.8 节)将会被调用。幂操作将一直调用一个标签函数。标准的数学库以预想的意义重定义了幂操作(参见 6.3 节)。

---------
4.5.3 关系运算符
---------
Lua 中的关系运算符是:
    == ~= < > <= >=
他们返回 nil 做为假,非 nil 做为真。

相等(==)首先比较两个操作数的标签。如果不同,结果为 nil。否则,比较它们的值。数值或字符串以常见的方式比较。表, userdata 和函数按引用比较,也就是说,两个比较的表只有是同一个的时候才被认为是相等的。不等运算 ~= 和相等运算 (==) 具有完全相反的结果。

4.2 节的转换规则不适用于相等比较。所以,"0"==0 的求值结果为 false,t[0] 和 t["0"] 表示表中不同的元素。

顺序比较操作符是这么工作的:如果两个参数都是数值,他们就以数值比较。如果两个参数都可以转化为字符串,它们将以字典序比较。否则的话, 标签方法 "lt" 将被调用(参见 4.8 节)。

---------
4.5.4 逻辑运算符
---------
Lua 中的逻辑运算符是:
    and or not
和控制结构一样,所有的逻辑运算符认为 nil 为假而其它的都为真。
合取运算符 and 返回 nil 如果它的第一个参数为 nil;否则,它返回它的第二个参数。析取运算符 or 返回它的第一个参数如果它不同于 nil;否则,它返回它的第第二个参数。and 和 or 是短路求值,也就是说,第二个操作数只在需要的时候才被求值。

有两个使用逻辑运算符的习惯用法。第一个是:
    x = x or v
它等价于
    if x == nil then x = v end
该用法当 x 未设置时给 x 设置一个默认值。
第二个习惯用法是:
    x = a and b or c
它应该被读为 x = (a and b) or c. 它等价于
    if a then x = b else x = c end
条件是 b 不为 nil。

---------
4.5.5 连接
---------
Lua 中的字符串连接操作符由两点“.." 表示。如果两个操作数是字符串或者数字,他们按 4.2 节的规则转化为字符串。否则,标签方法 "concat" 将被调用(参见 4.8 节)。

---------
4.5.6 优先级
---------
运算符的优先级如下表所示,从低到高排列:
    and or
    < > <= >= ~= ==
    ..
    + -
    * /
    not - (unary)
    ^
所有的二元操作符具体左结合性,^除外,幂操作具有右结合性。预编译可能重新排列相关运算符(比如 .. 和 +)的求值顺序,只要优化不改变正常的结果。反而,这些优化可能改变一些结果,如果你为这些运算符定义了一些不相关的标签方法。

---------
4.5.7 表的构造函数
---------
Table 的构造函数是创建表的表达式。当对构造函数求值的时候,会生成一个新的表。构造函数可以用来新建一个空表,或者新建一个表并初始化一些字段。
构造函数的语法如下:
    tableconstructor ::= `{‘ fieldlist `}‘
    fieldlist ::= lfieldlist | ffieldlist | lfieldlist `;‘ ffieldlist | ffieldlist `;‘ lfieldlist
    lfieldlist ::= [lfieldlist1]
    ffieldlist ::= [ffieldlist1]

lfieldlist1 被用来初始化列表。
    lfieldlist1 ::= exp {`,‘ exp} [`,‘]

列表中的表达式被赋值给一个连续的数值索引,索引从 1 开始。例如:
    a = {"v1", "v2", 34}
等同于:
    do
      local temp = {}
      temp[1] = "v1"
      temp[2] = "v2"
      temp[3] = 34
      a = temp
   end

ffieldlist1 初始化表中的其它字段:
    ffieldlist1 ::= ffield {`,‘ ffield} [`,‘]
    ffield ::= `[‘ exp `]‘ `=‘ exp | name `=‘ exp
例如:
    a = {[f(k)] = g(y), x = 1, y = 3, [0] = b+c}
等同于:
    do
      local temp = {}
      temp[f(k)] = g(y)
      temp.x = 1 -- or temp["x"] = 1
      temp.y = 3 -- or temp["y"] = 3
      temp[0] = b+c
      a = temp
    end

事实上, {x = 1, y = 4} 这样的表达式是表达式 {["x"] = 1, ["y"] = 4} 的语法糖。

两种形式都可以有一个可选的结尾逗号,并且在同样的构造中可以用分号分割。例如,下面的形式都是对的。
    x = {;}
    x = {"a", "b",}
    x = {type="list"; "a", "b"}
    x = {f(0), f(1), f(2),; n=3,}

---------
4.5.8 函数调用
---------
Lua 中的函数调用有如下语法:
    functioncall ::= varorfunc args
首先,varorfunc 被求值。如果它的值类型为 function,这个函数就用给定的参数被调用。 否则,标签方法 "function" 被调用,第一个参数为 varorfunc  的值,之后是原来的调用参数(参见 4.8 节)。

形如:
    functioncall ::= varorfunc `:‘ name args
可被用来调用 "methods"。v:name(...) 调用是 v.name(v, ...) 的语法糖,除了 v 只被求值一次。

参数的语法如下:
    args ::= `(‘ [explist1] `)‘
    args ::= tableconstructor
    args ::= literal
    explist1 ::= {exp1 `,‘} exp

所有参数表达式在函数调用前被求值。f{...} 调用是 f({...}) 的语法糖,即,参数列表是一个新建的 table。f‘...‘ (或者 f"..." 或者 f[[...]])调用是 f(‘...‘) 的语法糖,即,参数列表是一个字符串常量。

因为一个函数可以返回任意多个值(参见 4.4.3 节),返回值的个数在使用之前必须进行调整(参见 4.3 节)。如果一个函数调用作为语句使用(参见 4.4.5 节),它的返回结果会被调整到 0 个,因而返回值被全部丢弃。如果一个函数在需要一个值(语法中被表示为非终结的 exp1)的地方调用,它的返回结果会被调整到 1 个,因而除了第一个返回值其它的都被丢弃。如果一个函数在需要多个值的地方调用(语法上表示为非终结的 exp),不对返回结果个数进行调整。唯一可以保持多个值的地方是赋值的最后(或唯一)一个表达式,参数列表中,或者在 return 语句中。这里是一些例子:
    f() -- 调整到 0 个返回值
    g(f(), x) -- f() 调整到 1 个返回值
    g(x, f()) -- g 获得 x 和 f() 的所有返回值
    a,b,c = f(), x -- f() 调整到 1 个返回值 ( c 获得 nil )
    a,b,c = x, f() -- f() 调整到 2 个返回值
    a,b,c = f() -- f() 调整到 3 个返回值
    return f() -- 返回所有的 f() 的返回值
    return x,y,f() -- 返回 a, b, 和所有的 f() 的返回值

-------------------
4.5.9 函数定义
-------------------
函数定义的语法是:
    function ::= function `(‘ [parlist1] `)‘ block end
    stat ::= function funcname `(‘ [parlist1] `)‘ block end
    funcname ::= name | name `.‘ name | name `:‘ name

语句
    function f () ... end

    f = function () ... end
的语法糖。
语句
    function v.f () ... end

    v.f = function () ... end
的语法糖。

一个函数定义是一个可执行的表达式,它的值类型为 function。当 Lua 预编译一个 chunk,它所有的函数体也都会被预编译。然后,当 Lua 执行函数定义,它的 upvalue 就是确定的了(参见 4.6 节),函数也就实例化(或者闭合)了。这个函数实例(或者闭包)就是表达式的最终值。同样函数的不同实例可能有不同的 upvalue 。

参数和局部变量的表现一样,由参数值进行初始化。
    parlist1 ::= `...‘
    parlist1 ::= name {`,‘ name} [`,‘ `...‘]
当一个函数被调用时,实参的个数被调整为和形参一样(参见 4.3 节),除非函数是可变参数函数(vararg function),也就是参数列表的最后是三个点(‘...‘)。一个可变参数函数不需要调整它的实参列表;而是把所有额外的实参收集到名为 arg 的隐含参数中。arg 的值是一个表,它的一个字段 n 表示额外参数的个数,并且额外的参数位于 1, 2, ..., n 。

作为一个例子,考虑下面的定义:
    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, arg={n=0}
  g(3, 4)    a=3, b=4, arg={n=0}
  g(3, 4, 5, 8) a=3, b=4, arg={5, 8; n=2}
  g(5, r()) a=5, b=1, arg={2, 3; n=2}

结果由 return 语句返回(见 4.4.3节)。如果执行到函数最后也没有 return 指令的话,函数不返回值。

语法
    funcname ::= name `:‘ name
用来定义函数,函数有一个隐含的参数 self。

语句
    function v:f (...) ... end
只是
    v.f = function (self, ...) ... end
的语法糖。
注意函数获得一个额外的名为 self 的形式参数。
(未完待续)

时间: 2024-10-03 19:06:17

Lua4.0 参考手册(三)4.5的相关文章

Lua4.0 参考手册(一)1-3

说明:这个文档是 doc 目录里的 manual.html 文件.原文版权归原作者所有,这篇翻译只是作为学习之用.如果翻译有不当之处,请参考原文.-------------------以下是正文-------------------编程语言 Lua4.0 的参考手册--------------------------------------1 简介--------------------------------------Lua 是一个扩展编程语言,支持通用编程功能与数据描述功能.作为一个强大

Lua4.0 参考手册(八)6.2-6.5

(接上篇)-------------------6.2 字符串处理-------------------这个库提供字符串处理的通用函数,如查找,提取子串和模式匹配.在 Lua 中索引一个字符串的时候,第一个字符的索引是 1(不像 C 中是 0).另外,索引可以为负数,负数被解释为逆向索引,从字符串的结尾开始.所以,最后一个字符位置是 -1,以此类推. strbyte (s [, i])返回 s 的第 i 个字符的内部数值码(例如:ASCII 码).如果没有 i,它被认为是 1 .i 可以为负.

Lua4.0 参考手册(六)5.8-5.14

(接上篇)-------------------5.8 执行 Lua 代码-------------------一个宿主程序可以执行写在文件中或在字符串中的 Lua 块,使用下面的函数:     int lua_dofile (lua_State *L, const char *filename);     int lua_dostring (lua_State *L, const char *string);     int lua_dobuffer (lua_State *L, const 

Lua4.0 参考手册(二)4.1-4.4

(接上篇)--------------------------------------4 语言--------------------------------------这节描述 Lua 的词法,语法和语义. -------------------4.1 词法约定-------------------Lua 中的标识符可以是任何字母,数字,下划线组成的字符串,且首字母不可为数字.这符合大多数语言中标识符的定义,除了字母的字义依赖于当前的区域设置:所有的在当前的区域设置中被认为是字母的字符可以被用

Lua4.0 参考手册(四)4.6-4.8

(接上篇)-------------------4.6 可见性和 Upvalue-------------------一个函数体可以引用它自己的局部变量(包括它的参数)和全局变量,只要它们没有被函数中同名的局部变量所隐藏(shadowed ).一个不可以使用包含它的函数的局部变量,因为这样的变量可能在函数调用的时候已经不存在了.然而,一个函数可通过 upvalue 使用包含它的函数中的局部变量.upvalue 的语法如下:    upvalue ::= `%' name一个 upvalue 多少

Lua4.0 参考手册(七)6.1

(接上篇)--------------------------------------6 标准库--------------------------------------标准库提供了一些有用的函数,这些函数直接由标准 API 实现.因此,它们并非语言必需的部分,并且作为单独的 C 模块被提供.目前,Lua 有以下标准库:> 基本库:> 字符串处理:> 数学函数(sin, log, 等)> 输入输出(和一些系统功能) 为了能使用这些库,宿主程序必须调用函数 lua_baselibo

Lua4.0 参考手册(五)5.1-5.7

(接上篇)--------------------------------------5 API--------------------------------------这节描述 Lua 的 API, 也就是宿主程序和 Lua 交互的一组 C 函数.所有的 API 函数和相关联的类型及常量都在文件 lua.h 中声明. 所有的 API 提供的功能都可以由宏来替代,即使当我们使用术语函数(``function'').因为这样的宏只使用它的参数一次,所以不会产生隐蔽的副作用. ----------

Lua4.0 参考手册(九)7-8

(接上篇)--------------------------------------7 调试接口--------------------------------------Lua 没有内置的调试功能.而是借助于函数和钩子(hook)提供了一个特殊接口,可以用来构建不同种类的调试器,分析器(profile)和一些其它的需要解释器内部信息的工具.这个接口在 luadebug.h 文件中声明. -------------------7.1 栈和函数信息-------------------获得解释器

Vue.js 2.0 参考手册.CHM下载

下载地址 Vue.js 2.0 参考手册.CHM下载链接: http://pan.baidu.com/s/1kVbhd4b 密码: wxfh