一:函数
1.Lua中的函数是带有词法界定的第一类值。第一类值是指在Lua中函数和其他值一样,函数可以被存放在变量中,也可以存放在表中,可以作为函数的参数,还可以作为函数的返回值。词法界定是指嵌套的函数可以访问其他外部函数中的变量。
1.1闭合函数:指一个函数加上该函数所需访问的所有“所有非局部的变量”(也可称为外部的局部变量 upvalue).如下面例子的i,就是非局部变量.
function count()
local i = 1--非局部变量 不会被重置 在上次的基础上--
return function()
i=i+1
return i
end
end
local func = count()
print(func()) --2--
print(func()) --3--
1.2非全局函数:使用local定义的函数。需要注意当一个函数要使用另一个非全局函数时,应要前向声明,否则报错。
local test1;
--非全局函数--
local function test()
print(123)
--test1()--
test1() --需要前置声明 见29行
end
test1 = function(...)
print(123)
end
--test调用--
test()
1.3尾调用:类似在函数结尾的goto调用,当函数最后一个动作是调用另外一个函数时,我们称这种调用为尾调用。
local lfunc;
local pfunc;
lfunc = function()
print("lfunc")
end
function pfunc()
return lfunc();
end
print(pfunc())
二:迭代器与泛型for
迭代器需要保留上一次成功调用的状态和下一次成功调用的状态,也就是它知道来自于哪里以及将要去往哪里。闭包提供的机制可以很容易实现这个任务。
*闭包是一个内部函数,它可以访问一个或者多个外部函数的外部局部变量。每次闭包的成功调用后外部局部变量都保存他们的值(状态)。当然如果要创建一个闭包必须要创建其外部局部变量。所以一个典型的闭包的结构包括两个函数:一个是闭包自己;另一个是工厂(创建闭包的函数)。
--[[迭代器的实现--]]
function iteratorFun(t)
local i = 0
return function()
i = i + 1
return t[i]
end
end
t = {1,2,3}
--[[
local func = iteratorFun(t)--避免iteratorFun(t)()每次都会初始化--
print(func())
print(func())
--]]
function forFun(t)
local iter = iteratorFun(t);--返回函数指针--
print(iter)
while true do
local value = iter()
if value == nil then
break;
end
print(value)
end
end
--[[也可直接用for in 直接输出值--]]
for value in iteratorFun(t) do
print(value)
end
a = {"hello","my","darling","how are you"}
--[[forFun(a)--]]
--返回两个值的迭代器--
function dieDaiQi(a)
local i = 0
return function()--尾调函数--
i = i+1
if i > #a then
return nil;
end
return i,a[i]
end
end
print("打印结果:")
for k,v in dieDaiQi(a) do
print(k,v)
end
print("*******************for in do****************")
--for in do
function forInDo(t)
--_f迭代器函数 _s恒定状态 _var控制变量初始值
local _f,_s,_var = dieDaiQi(t)
while true do
local k , v = _f(_s,_var)
_var = k;
if(_var == nil) then
break;
end;
print(k..":"..v)
end
end
forInDo(a)
四:协同程序
4.1协同程序(coroutine)与多线程情况下的线程比较类似:有自己的堆栈,自己的局部变量,有自己的指令指针(IP),但与其他协同程序共享全局变量等很多信息。线程和协同程序的主要不同在于:在多处理器情况下,从概念上来讲多线程程序同时运行多个线程;而协同程序是通过协作来完成,在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只在必要时才会被挂起。
4.2Lua所有的协同函数都存放在coroutinue table中。create函数用于创建新的协同程序,其只有一个参数:一个函数,即协同程序将要运行的代码。若一切顺利,返回值为thread类型,表示创建成功。通常情况下,create的参数是匿名函数:
--协同程序 默认挂起状态--
local co = coroutine.create(function()
print("coroutine")
end)
print(co) -->返回thread类型 输出为 thread:006FFE70
4.3协同有三个状态:挂起(suspended) 、运行(running)、终止(dead)。当我们创建协同程序成功时,其为挂起太,即此时协同程序并未运行。我们可以用status函数来检查协同的状态。
4.4函数coroutine.resume使协同程序由挂起态变为运行态,当完成相应的功能后,任务完成,便进入终止态(dead)。
cortinue.resume(co) -->coroutine
print(coroutine.status(co)) -->dead
4.5协同真正的强大之一在于yield函数,它可以将正在运行的代码挂起。当我们激活被挂起的程序时,将从函数yield的位置继续执行程序,知道再次遇到yield或程序结束。如果在最后一次调用时,即协同程序处于终止态,若我们仍然希望激活它时,resume将返回false和错误信息。
注:resume运行在保护模式下,因此,如果协同程序内部存在错误,Lua并不会抛出错误,而是将错误返回给resume函数。
4.6协同的强大之二在于可以通过resume-yield来交换数据。
1)resume除第一个参数外后面的实参可以传递给create函数中的匿名函数的形参中去。
co = coroutine.create(function (a,b,c)
print("co", a,b,c)
end)
coroutine.resume(co, 1, 2, 3) --> co 1 2 3
2)数据可由yield传给resume。resume有两个返回值,若调用成功,则第一个返回值为true,第二个错误信息则为yiedf的参数。
3)数据可由resume的参数传递给yield,即yield的返回值为resume的参数。
--[[
①resume的实参传递给create回调函数的形参
②yield函数的参数可以传递到resume的第二个返回值
--]]
print("************resume的实参传递给create回调函数的形参****************")
local co3 = coroutine.create(function(param)
print(param)
coroutine.yield("yield函数的参数[测试是否可以传给resume的第二个返回值]")
end)
local result,msg = coroutine.resume(co3,"param");
print("co3 result:",result)
print("co3 msg:",msg)
--[[③yield函数的返回值是resume的第二个参数
--]]
local co4 = coroutine.create(function(name)
for i = 1,2,1 do
print(name)
local result = coroutine.yield("yield函数的参数")
print("yield函数的返回值:",result)-->yield的返回值为name2
end
end)
local result1,error1 = coroutine.resume(co4,"name1")
local result2,error2 = coroutine.resume(co4,"name2")
print("co4_1 result1:",result1," ","co4_1 error1:",error1)
print("co4_2 result2:",result2," ","co4_2 error2:",error2)
print("status:",coroutine.status(co4))--执行了两次挂起 所以还是挂起状态 需要再执行一次就dead状态