lua

lua笔记

Posted by Chen on August 1, 2020

1. 数组长度

	local t1 = { "A", "B", "C" }
	local t2 = { [1] = "A", [2] = "B", [3] = "C" }
	local t3 = { [10] = "a"}
	--[[
		t1 和 t2的差别:
		t1 可以理解为 数组
		t2 可以理解为 字典

		#t1 == 3
		#t2 == 3
		#t3 == 0

		当 t1[2] = nil 时: #t1 == 3
		当 t2[2] = nil 时: #t2 == 1
		你觉的 当 它们 idx为2 的 值为 nil时: 使用#取长度 都为3, 实际不然.


		数组类型的 删除: table.remove(t, idx)
		字典类型的 删除: t[key] = nil
	]]

2. lua中真假判断

lua 中 nilfalse 为 假, 其他都为 真, 同时注意 nil ~= false

3. 逻辑运算符

Lua 中逻辑操作符有 and or 和 not

not 只会返回 true 或 false

and 和 or 都有 短路性

-- and
print(nil and 1)     -- 输出 nil
print(false and 1)   -- 输出 false
print(true and 1)    -- 输出 1
print(0 and 1)       -- 输出 1

-- or
print(nil or 1)      -- 输出 1
print(false or 1)    -- 输出 1
print(true or 1)     -- 输出 true
print(0 or 1)        -- 输出 0

替换 if else : m = a and b or c 著名的 三目运算符

注意: c中 int a = true ? 0 : 2 结果 a == 0 lua中 a = true and false or 1 结果 a == 1

4. 尾调用

Lua 支持 尾调用 ( Tail Call ) 消除.尾调用是指一个函数调用另一个函数的最后一个动作时,该调用才算是一条”尾调用”.第一种写法之所以会造成栈溢出是因为函数 sum 的递归调用完后还需要做一次加法运算,因此不是尾调用.而第二种写法避免了调用后的加法运算,因此是尾调用,因此不会每次递归都压栈 (其性能和 goto 语句效率差不多).如果在写代码的过程中,使用”递归”算法很方便的话,而且能写成”尾调用”的话,那么,就尽情的用吧(代码可读性要高啊)!其实这个特性适用于任何支持尾调用优化的语言.

	-- 计算前 n 项和(不推荐这么写)
	function sum(x)
	    if x <= 0 then
	        return 0
	    else
	        return x + sum(x - 1)
	    end
	end

	-- 计算前 n 项和(求前 n 项和也不推荐这么写,这里只是作为例子进行讲解用)
	function sum(x, res)
	    if x <= 0 then
	        return res
	    else
	        return sum(x - 1, res + x)
	    end
	end

5. table.insert 和 select 配合使用

	function testFunc(...)
		local ret = {}
		for i = 1, select("#", ...) do
		    table.insert(ret, select(i, ...))
		end
	end
	--[[
		这么写会 报错 `wrong number of arguments to 'insert'`
		因为select(i, ...) 会返回 索引i之后的全部参数

		所以我们 使用 () 让 select 返回一个数值
	]]
	function testFunc(...)
		local ret = {}
		for i = 1, select("#", ...) do
		    table.insert(ret, (select(i, ...)))
		end
	end

6. 赋值

	a, b = 1, 2

	a, b = b, a
	--赋值过程是先计算赋值符号右边的每一项,然后同时赋值给右边的变量 上边 a == 2; b == 1

7. continue

lua 里面貌似没有continue语句,实现continue功能可以嵌套一层循环,然后利用内层循环的break实现

	for i = 1, 10 do
		for j = 1, 1 do
			if i % 2 == 0 then
				break
			end

			print("i----", i)
		end
	end

8. 函数loadfile也是从文件中加载Lua代码段,但它不会运行代码,而只是编译代码,然后将编译后的代码段作为一个函数返回

9. 通常,_G和_ENV指向的是同一个表

10. 调用父类的正确写法

self.super.Move(self, x, y, z).而不能直接 self.super:Move(x, y, z).因为后者由于lua的语法糖,传递给Move的参数是super,而实际上这个时候我们期望传递的是self.