2016-06-28 24 views
3

我为此video tutorial学习卢阿,它有这段代码:混淆LUA corountine的简历和产量的功能

co = coroutine.create(function() 
    for i=1,5 do 
     print(coroutine.yield(i)) 
    end 
    end) 

print(coroutine.resume(co,1,2)) 
print(coroutine.resume(co,3,4)) 
print(coroutine.resume(co,5,6)) 
print(coroutine.resume(co,7,8)) 
print(coroutine.resume(co,9,10)) 
print(coroutine.resume(co,11,12)) 

输出是这样的:

true 1 
3 4 
true 2 
5 6 
true 3 
7 8 
true 4 
9 10 
true 5 
11 12 
true 

但我不不要理解yield和resume如何将参数传递给对方,为什么yield不会输出继续传递给它的第一个1,2,请问有人能解释一下吗?由于

回答

5

普通Lua函数有一个条目(其中的论点获得通过)和一个出口(其中的返回值被传递出来):

local function f(a, b) 
    print("arguments", a, b) 
    return "I'm", "done" 
end 

print("f returned", f(1, 2)) 
--> arguments  1  2 
--> f returned  I'm  done 

的参数被绑定到参数名称(局部变量)通过将它们放在圆括号内,可以通过将函数调用表达式放在赋值语句的右侧或更大的表达式(例如另一个函数调用)中来检索作为return语句的一部分列出的返回值。

还有其他方法可以调用函数。例如。 pcall()调用一个函数并捕获可能在内部引发的任何运行时错误。通过将参数放入pcall()函数调用(函数本身之后)来传入参数。 pcall()还预先指定了一个附加的返回值,该值指示函数是正常退出还是通过错误退出。被调用函数的内部不变。

print("f returned", pcall(f, 1, 2)) 
--> arguments  1  2 
--> f returned  true I'm  done 

您可以通过使用coroutine.resume()代替pcall()调用一个协同程序的主要功能。的方式传递参数,而额外的返回值保持不变:

local th = coroutine.create(f) 
print("f returns", coroutine.resume(th, 1, 2)) 
--> arguments  1  2 
--> f returns  true I'm  done 

但随着协同程序你会得到另一种方式(临时)退出功能:coroutine.yield()。您可以通过coroutine.yield()将值作为参数传递给yield()函数调用来传递值。这些值可作为coroutine.resume()调用的返回值而不是正常返回值在外部检索。

但是,您可以再次调用coroutine.resume()来重新输入已生成的协同程序。协程继续停止,并且传递给coroutine.resume()的额外值可用作暂停协程的yield()函数调用的返回值。

local function g(a, b) 
    print("arguments", a, b) 
    local c, d = coroutine.yield("a") 
    print("yield returned", c, d) 
    return "I'm", "done" 
end 

local th = coroutine.create(g) 
print("g yielded", coroutine.resume(th, 1, 2)) 
print("g returned", coroutine.resume(th, 3, 4)) 
--> arguments  1  2 
--> g yielded  true a 
--> yield returned 3  4 
--> g returned  true I'm  done 

请注意,yield不需要直接在协程的主函数中,它可以在嵌套函数调用中。执行跳回到coroutine.resume()(重新)启动协程。

现在你的问题为什么你的输出中没有出现第一个resume()1, 2:你的协同主函数没有列出任何参数,所以忽略了所有传递给它的参数(在第一个函数入口处)。在类似的说明中,由于你的main函数没有返回任何返回值,所以除true之外,最后的resume()不会返回任何额外的返回值,这也表示成功执行。

2
co = coroutine.create(function() 
    for i=1,5 do 
     print(coroutine.yield(i)) 
    end 
    end) 

我们开始使用协程的第一次:

print(coroutine.resume(co,1,2)) 

它将运行直到第一个产量。我们的第一个恢复调用将返回true,并解释第一个输出行的yield(这里是i = 1)参数。

我们的协程现在暂停。一旦我们调用恢复第二次:

print(coroutine.resume(co,3,4)) 

你的第一个产量终于回来了,并且当前的简历(3,4)的参数将被打印出来。 for循环第二次迭代开始,coroutine.yield(2)被调用,同时再次使您的最后一次恢复返回true的协程,2等等

所以实际上在你的例子中coroutine.resume(co)会无论如何,任何进一步的参数都会丢失,足以应付第一个电话。

+0

感谢您的回答。这是否意味着yield函数在返回之前实际上将其参数传递给了resume函数? – Demonedge

+0

如果恢复过程中没有错误,则返回true。 – Piglet