Dawnworld 2019-12-23
下面讲一些lua 常见的用法和规则,可以为学习理解lua带来帮助。
lua把 nil 和false 视为“假”,其他都为“真”
lua的and or 可以用来构成三元表达式,如下:
> = 1 == 1 and 1 or 2 1
但如果是这样写,就不是你想要的结果了:
> = 1 == 1 and false or true true
这是因为,and 运算符判定 false不成立,就继续执行了 or 运算符的结果(nil和false lua都认为为假)
如果你一定要返回 true 或 false,要这么写:
> = ( 1 == 1 and {false} or {true} )[1] false
local var1=1,var2
以上 ,var1和var2的作用域不同,var1是所在作用域的变量,var2可能是全局变量。实际上述命令解释后为 var1 取 "1,var2" 组成的值第一个值,类似 local var1 = ...
请注意变量的声明,如果不确定,就老老实实依依赋值。
local var1 local var2=1 print(var1) --nil print(var2) --1 print("=====") local var3 =1,var4 print(var3) --1 print(var4) --nil print("=====") local var5, var6=1 print(var5) --1 ->是不是很奇怪- -、这里的var5竟然是1 print(var6) --nil
if a == {} then
结果是false,这是一个逻辑错误,实际比较table a的内存地址和一个匿名table的是否相同
正确的写法是:
if next(a) == nil then
name,name = 1,2
那name等于多少呢?
实际上name值为1,可以写个小例子 a,b = 2,3,4打印就可以看到了。a=2,b=3
t[name]与t["name"], t.name
第一种和后两种是不同的,第一种会根据取name的值做key,后两种以 "name"做key。这种情况还有:
t = {[name] = 1}
t = {name = 1}
t = {["name"] = 1}
取得 table 长度最常用的做法是 #table,如下:
> t = {1,2,3} > #t 3
但 # 操作符也是有局限的,不支援数组以外的对象计算,所以要谨记
> t = { 10, n = 20, 30, 40 } > #t 3 --长度是4,所以,要采用其他方式判定长度
另外,通过把元素设 nil 无法改变 #table 的结果(除非是数组最后一个元素);而 table.remove 则可以立即更新 #table 的结果
t ={1,2,3} t[1]=nil print(#t) --3 table.remove(t,1) print(#t) --2
将一个table复制给另外一个table,修改这个新的table值会影响原来的table,但通过clone可以改变这一行为
function deepcopy(orig) local orig_type = type(orig) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in next, orig, nil do copy[deepcopy(orig_key)] = deepcopy(orig_value) end setmetatable(copy, deepcopy(getmetatable(orig))) else -- number, string, boolean, etc copy = orig end return copy end
function f123() return 1, 2, 3 end function f456() return 4, 5, 6 end print(f123()) --1 2 3 print(f456()) --4 5 6 print(f123(), f456()) -- 1 4 5 6 print(f456(),1) --4 1
如果函数不是处于列的最后一个,只返回一个值
这是浮点数都会有的精度丢失问题,lua也有这个问题。再看下整数与浮点数的比较
> =10==10.00000000000000000 true > =10==10.00000000000000001 true > =10==10.00000000000000000 true > =10==9.999999999999999999 true
所以,这边测试了一下,lua 的浮点数会精确到15位,所以在比较精确的比较之前确认好精度在进行比较
冒号语法可以用来定义函数, 这样的话,函数会有一个隐式的形参 self。
写法如下:
? function t:f (params) body end
冒号语法实际上是一种语法糖,等效于:
? t.f = function (self, params) body end
local t={a=123} function t.f1(self, p) print(self.a, p) --self.a 访问t中a的值 end function t:f2(p) print(self.a, p) end t:f1(1) t.f1(t,1) t:f2(1) t.f2(t,1)
以上几个结果都是 123 1
这里,通过冒号方式调用函数不需要加入self参数,而点号则需要。
当一个函数内部嵌套另一个函数定义时,内部的函数体可以访问外部的函数的局部变量,这种特征我们称作词法定界。
function fn() local i = 0 return function() -- 注意这里是返回函数的地址,不是执行 i = i + 1 return i end end c1 = fn() -- 接收函数返回的地址 print(c1()) --> 1 --c1()才表示执行 ,i 此时为0 print(c1()) --> 2 --继续执行函数体 此时i =1上次执行的结果
如上,调用c1()时,fn函数明显已经返回,lua闭包闭包思想正确处理这种情况:
如果我们再次调用fn,将创建一个新的局部变量i:
c2 = fn() print(c2()) --> 1 print(c1()) --> 3 print(c2()) --> 2
function f(x) return g(x) -- 类似于goto g(x)函数的地址 end
例如下面调用不论n为何值不会导致栈溢出。
function foo (n) if n > 0 then return foo(n - 1) end end
需要注意的是:必须明确什么是尾调用。
一些调用者函数调用其他函数后也没有做其他的事情但不属于尾调用。比如:
function f (x) g(x) return end
上面这个例子中f在调用g后,不得不丢弃g地返回值,所以不是尾调用,同样的下面几个例子也不时尾调用:
return g(x) + 1 -- 还需+1 return x or g(x) -- 还需比较 return (g(x)) -- 还需调整为一个返回值
表格的现在还是较为常用的一种标签,但不是用来布局,常见处理、显示表格式数据。在HTML网页中,要想创建表格,就需要使用表格相关的标签。<table> <tr> <td>单元格内的文字</td> ...