setmetatable(_G,{ __newindex = function(t,n,v) local w = debug.getinfo(2,"S").what if w ~= "main" and w ~= "C" then error("attempt to write to undeclared variable"..n,2) end rawset(t,n,v) end, __index = function(_,n) error("not exsits "..n,2) end }) a = 100 print(a)
因为全局变量都是保存在一个_G的table中的,所以可以改变它的元方法达到限制新索引的添加
rawset和rawget方法可以跳过元表的元方法。
Lua的全局变量其实都是整合到一个加_G的table中的,在任何地方都可以修改和创建全局变量。这个非常方便,但是全局变量的修改就会影响到所有程序,还是小心为妙。
for n in pairs(_G) do print(n)--打印所有的全局变量 end
--2.lua function test(a,b) print(a+b) end
--3.lua function testDo(a,b) print(a+b) end print('DoFile')
f = loadstring('print(123)') f() t = loadfile('2.lua') --只是编译 t() --先定义test方法 test(1,2) --3 d = dofile('3.lua') --DoFile,直接编译了,然后定义 testDo(5,3) --8 s = loadfile('5.lua') print(s) --nil,dofile会发生错误
在语言运行时,有能力且轻易的执行动态生成的代码,有了这些dofile等才可以将Lua称为一种解析型语言。
a = {"one","two","three"} for i,v in pairs(a) do print(i,v) end for i,v in next,a,nil do print(i,v) end
pairs使用的迭代器是next(table,key),如果key值为nill就返回第一个值,如果是某一个key值(index下标的),就从它的下一个index开始。如果是一个keyName值,就会随机遍历整个table
a = {"one","two","three"} for i,v in ipairs(a) do print(i,v) end local function iter(a,i) i = i+1 local v = a[i] if v then return i,v end end function ipairss(a) return iter,a,0 end for i,v in ipairss(a) do print(v) --和ipairs的输出一样 end
可以看出,for使用迭代器,in需要获3个参数,迭代器函数、恒定状态、控制变量初始值
function newCounter() local i = 0 return function() i = i+1 return i end end c = newCounter() print(c()) --1 print(c()) --2 c2 = newCounter() print(c2()) --1 print(c()) --3 print(c2()) --2
在newCounter中返回了一个闭合函数,使用到了一个newCounter的局部变量i,但是返回的闭合函数使用的i是保留存在的
调用新的newCounter会产生一个新的i,值是独立的,看上面代码的输出。
function go(arg) return realGO(arg.bdel,arg.del) end function realGO(bdel,del) return bdel - del end local val = go({bdel=100,del=30}) print(val)
这是一种技巧,将参数以table的形式传递,可以在任意位置指定某个参数的值,就不需要记住参数的排放位置了
也可以在伪调用的函数里做一些参数的验证和判断或则设置默认值。
function go(...) for i,v in ipairs{...} do print(v) end end function goo(...) for i=1,select('#',...) do print(select(i,...)) end end go(5,nil,1) --5 goo(nil,1,5,9) --4行 nil,1,5,9 1,5,9 5,9 9
变长参数只要只用...代表就可以了,...代表一个数组吧
使用ipairs访问变长数组会遇到nil值就停止,如果参数中存在nil,那么后面的值将无法访问
使用select可以访问包含nil值,select('#',...)表示取这个数组的长度,select(1,...)表示返回第一个及后面所有,select(2,...)表示返回第二个及后面所有......所以要获取具体第几位的参数值,只需要一个临时变量来去承接返回来的第一个值,其他舍弃调就行了。
t = {"nihao",fg="asd"} t[10] = 'love' print(unpack(t)) --nihao print(t.fg) --asd print(t[10]) --love t[2] = 100 t[3] = nil t[4] = 200 print(unpack(t)) --nihao 100 nil 200
unpack函数会从table的下标1开始,一直往上递增,直到遇到nil索引为止
function f1() return 1 end function f2() return 1,2 end t = {f1(),f2()} print(unpack(t)) --1,1,2 t2 = {f1(),f2(),5} print(unpack(t2)) --1,1,5 t3 = {f1(),f2(),f2(),f2()} print(unpack(t3)) --1,1,1,1,2
可以看出当用function的返回值来构造table时,table前面function只会用到第一个返回值,之后table最后一个元素且是函数的函数会返回所有的返回值