读一读

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最后一个元素且是函数的函数会返回所有的返回值