当前位置 博文首页 > 做自己擅长的事:Lua知识点二

    做自己擅长的事:Lua知识点二

    作者:[db:作者] 时间:2021-07-15 09:59

    1表达式

    1.1算术运算符

    二元运算符:+ - * / ^ (加减乘除幂)
    一元运算符:- (负值)
    这些运算符的操作数都是实数。

    1.2关系运算符

    < > <= >= == ~=
    Lua比较数字按传统的数字大小进行,比较字符串按字母的顺序进行,但是字母顺序依赖于本地环境。

    1.3逻辑运算符

    and or not
    逻辑运算符认为false和nil是假(false),其他为真,0也是true.

    连接运算符

    ..
    字符串连接,如果操作数为数字,Lua将数字转成字符串。

    优先级

    ^
    not - (unary)
    * /
    + -
    ..
    < > <= >= ~= ==
    and
    or
    除了^和..外所有的二元运算符都是左连接的。

    表的构造

    构造器是创建和初始化表的表达式。表是Lua特有的功能强大的东西。最简单的构造函数是{},用来创建一个空表。
    不管用何种方式创建table,我们都可以向表中添加或者删除任何类型的域,构造函数仅仅影响表的初始化。
    每次调用构造函数,Lua都会创建一个新的table,可以使用table构造一个list:
    不推荐数组下标从0开始,否则很多标准库不能使用
    在构造函数的最后的”,”是可选的,可以方便以后的扩展。
    在构造函数中域分隔符逗号(”,”)可以用分号(”;”)替代,通常我们使用分号用来分割不同类型的表元素。

    2基本语法

    2.1赋值语句

    赋值是改变一个变量的值和改变表域的最基本的方法。
    a = “hello” .. “world”
    t.n = t.n + 1
    Lua可以对多个变量同时赋值,变量列表和值列表的各个元素用逗号分开,赋值语句右边的值会依次赋给左边的变量。
    a, b = 10, 2*x <–> a=10; b=2*x
    遇到赋值语句Lua会先计算右边所有的值然后再执行赋值操作,所以我们可以这样进行交换变量的值:
    x, y = y, x – swap ‘x’ for ‘y’
    a[i], a[j] = a[j], a[i] – swap ‘a[i]’ for ‘a[i]’
    当变量个数和值的个数不一致时,Lua会一直以变量个数为基础采取以下策略:
    a. 变量个数 > 值的个数 按变量个数补足nil
    b. 变量个数 < 值的个数 多余的值会被忽略
    例如:
    a, b, c = 0, 1
    print(a,b,c) –> 0 1 nil

    a, b = a+1, b+1, b+2 – value of b+2 is ignored
    print(a,b) –> 1 2

    a, b, c = 0
    print(a,b,c) –> 0 nil nil
    上面最后一个例子是一个常见的错误情况,注意:如果要对多个变量赋值必须依次对每个变量赋值。
    a, b, c = 0, 0, 0
    print(a,b,c) –> 0 0 0
    多值赋值经常用来交换变量,或将函数调用返回给变量:
    a, b = f()
    f()返回两个值,第一个赋给a,第二个赋给b。

    局部变量与代码块(block)

    使用local创建一个局部变量,与全局变量不同,局部变量只在被声明的那个代码块内有效。代码块:指一个控制结构内,一个函数体,或者一个chunk(变量被声明的那个文件或者文本串)。
    注意,如果在交互模式下上面的例子可能不能输出期望的结果,因为第二句local i=1是一个完整的chunk,在交互模式下执行完这一句后,Lua将开始一个新的chunk,这样第二句的i已经超出了他的有效范围。可以将这段代码放在do..end(相当于c/c++的{})块中。
    应该尽可能的使用局部变量,有两个好处:
    1. 避免命名冲突
    2. 访问局部变量的速度比全局变量更快.
    block划定一个明确的界限:do..end内的部分。当你想更好的控制局部变量的作用范围的时候这是很有用的。

    控制结构语句

    控制结构的条件表达式结果可以是任何值,Lua认为false和nil为假,其他值为真。
    if语句,有三种形式:
    if conditions then
    then-part
    end;

    if conditions then
    then-part
    else
    else-part
    end;

    if conditions then
    then-part
    elseif conditions then
    elseif-part
    .. —>多个elseif
    else
    else-part
    end;
    while语句:
    while condition do
    statements;
    end;
    repeat-until语句:
    repeat
    statements;
    until conditions;

    for语句有两大类:
    第一,数值for循环:
    1. 三个表达式只会被计算一次,并且是在循环开始前。
    2. 控制变量var是局部变量自动被声明,并且只在循环内有效.
    3. 循环过程中不要改变控制变量的值,那样做的结果是不可预知的。如果要退出循环,使用break语句。
    第二,范型for循环:
    for i,v in ipairs(a) do print(v) end
    范型for遍历迭代子函数返回的每一个值。
    范型for和数值for有两点相同:
    1. 控制变量是局部变量
    2. 不要修改控制变量的值

    break和return语句

    break语句用来退出当前循环(for、repeat、while)。在循环外部不可以使用。
    return用来从函数返回结果,当一个函数自然结束时,结尾会有一个默认的return。(这种函数类似pascal的过程(procedure))
    Lua语法要求break和return只能出现在block的结尾一句

    3函数

    返回多值

    Lua函数可以返回多个结果值,比如string.find,其返回匹配串“开始和结束的下标”(如果不存在匹配串返回nil)。
    s, e = string.find(“hello Lua users”, “Lua”)
    print(s, e) –> 7 9
    Lua总是调整函数返回值的个数以适用调用环境,当作为独立的语句调用函数时,所有返回值将被忽略。
    第一,当作为表达式调用函数时,有以下几种情况:
    1. 当调用作为表达式最后一个参数或者仅有一个参数时,根据变量个数函数尽可能多地返回多个值,不足补nil,超出舍去。
    2. 其他情况下,函数调用仅返回第一个值(如果没有返回值为nil)
    第二,函数调用作为函数参数被调用时,和多值赋值是相同。
    第三,函数调用在表构造函数中初始化时,和多值赋值时相同。
    另外,return f()这种形式,则返回“f()的返回值”:
    可以使用圆括号强制使调用返回一个值。
    函数多值返回的特殊函数unpack,接受一个数组作为输入参数,返回数组的所有元素。

    可变参数

    Lua函数可以接受可变数目的参数,和C语言类似在函数参数列表中使用三点(…)表示函数有可变的参数

    命名参数

    rename(old=”temp.lua”, new=”temp1.lua”)

    闭包

    当一个函数内部嵌套另一个函数定义时,内部的函数体可以访问外部的函数的局部变量,这种特征我们称作词法定界。
    闭包是一个函数以及它的upvalues。如果我们再次调用newCounter,将创建一个新的局部变量i,因此我们得到了一个作用在新的变量i上的新闭包。
    闭包在上下文环境中提供很有用的功能,如前面我们见到的可以作为高级函数(sort)的参数;作为函数嵌套的函数(newCounter)。
    闭包在完全不同的上下文中也是很有用途的。因为函数被存储在普通的变量内我们可以很方便的重定义或者预定义函数。

    非全局函数

    Lua中函数可以作为全局变量也可以作为局部变量,我们已经看到一些例子:函数作为table的域(大部分Lua标准库使用这种机制来实现的比如io.read、math.sin)。
    1. 表和函数放在一起
    Lib = {}
    Lib.foo = function (x,y) return x + y end
    Lib.goo = function (x,y) return x - y end
    2. 使用表构造函数
    Lib = {
    foo = function (x,y) return x + y end,
    goo = function (x,y) return x - y end
    }
    3. Lua提供另一种语法方式
    Lib = {}
    function Lib.foo (x,y)
    return x + y
    end
    function Lib.goo (x,y)
    return x - y
    end

    正确的尾调用(Proper Tail Calls)

    Lua中函数的另一个有趣的特征是可以正确的处理尾调用(proper tail recursion,一些书使用术语“尾递归”,虽然并未涉及到递归的概念)。

    cs