首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >卢冠华简历与产量函数的混淆

卢冠华简历与产量函数的混淆
EN

Stack Overflow用户
提问于 2016-06-28 07:28:56
回答 3查看 3.6K关注 0票数 4

我是通过这个视频教程学习lua的,它有一段代码:

代码语言:javascript
复制
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))

输出如下:

代码语言:javascript
复制
true    1
3   4
true    2
5   6
true    3
7   8
true    4
9   10
true    5
11  12
true

但是我不明白产量和简历是如何互相传递参数的,为什么产量没有输出第一个1,2的简历传递给它,有人能解释一下吗?谢谢

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-06-28 12:11:02

普通Lua函数有一个条目(在其中传递参数)和一个出口(其中传递返回值):

代码语言:javascript
复制
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()还添加了一个额外的返回值,该值指示函数是正常退出还是通过错误退出。被调用函数的内部保持不变。

代码语言:javascript
复制
print( "f returned", pcall( f, 1, 2 ) )
--> arguments       1       2
--> f returned      true    I'm     done

您可以使用coroutine.resume()而不是pcall()来调用coroutine的主函数。传递参数的方式和额外的返回值保持不变:

代码语言:javascript
复制
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在停止的地方继续,传递给coroutine.resume()的额外值可以作为以前挂起协同线的yield()函数调用的返回值。

代码语言:javascript
复制
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

注意,产量不需要直接在主函数中的协同线,它可以在一个嵌套函数调用。执行跳回(重新)启动协同线的coroutine.resume()

现在来问为什么输出中没有出现来自第一个1, 2resume():您的coroutine函数没有列出任何参数,因此忽略了传递给它的所有参数(在第一个函数条目上)。同样,由于主函数不返回任何返回值,最后一个resume()除了表示成功执行的true之外,不返回任何额外的返回值。

票数 9
EN

Stack Overflow用户

发布于 2016-06-28 12:16:53

代码语言:javascript
复制
co = coroutine.create(function()
    for i=1,5 do
      print(coroutine.yield(i))
    end
  end)

我们第一次使用以下方法启动协同线:

代码语言:javascript
复制
print(coroutine.resume(co,1,2))

它将一直持续到第一次屈服。我们的第一个简历调用将返回true和收益率参数(这里i= 1),这说明了第一条输出线。

我们的协同线现在暂停了。一旦我们第二次调用简历:

代码语言:javascript
复制
print(coroutine.resume(co,3,4))

您的第一个收益最终返回和您的当前简历(3,4)的参数将打印出来。for循环第二次迭代开始,coroutine.yield(2)被调用,它支持协同线,这将再次使您的最后一次简历返回为真,2等等

因此,实际上,在您的示例中,coroutine.resume(co)对于第一个调用就足够了,因为任何进一步的参数都会丢失。

票数 2
EN

Stack Overflow用户

发布于 2020-05-27 00:08:58

我们看到这种行为的原因是微妙的,但这与“输入”和“退出”yield语句的不匹配有关。它还与匿名函数中调用printyield的顺序有关。

让我们想象一下print(coroutine.yield(i))执行与迭代的关系图。

在第一次迭代中,我们让coroutine.resume12传递给协同线。这是起始点,所以我们不是从(以前的 yield )中提取的,而是匿名函数本身的原始调用。在打印中调用yield,返回i=1,但不调用print。函数退出。

下面是函数挂起一段时间,然后才能看到下一个coroutine.resume、.This、resume、passes、34恢复。函数在最后一次 yield中获得。还记得print函数没有被调用,因为第一个yield首先被调用并退出了程序?执行在print内部返回,所以现在调用print,但这次返回34,因为这是要传输的最新值。函数再次重复,在print之前调用print,然后返回i=2

如果我们继续迭代,我们将更确切地了解为什么我们没有看到12的模式。我们的第一次迭代是“退出”产量,而不是对应的“输入产量”。这相当于协同线co的第一次执行。

我们可能期望最后一个yield也不成对,但区别是我们将有一个“输入”yield,它是未配对的,而不是一个“退出”的yield,它是未配对的。这是因为循环已经完成了。这解释了为什么我们看到11 12后面跟着true,没有“退出”yield返回。

这种情况与内部for循环的奇偶性无关。唯一重要的是resumeyield对以及它们的处理方式。您必须意识到,yield不会在resume的第一次调用中返回函数中的值,该值最初用于调用协同线内的函数。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38069751

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档