←  Tutorials

ComputerCraft | Programmable Computers for Minecraft

»

Advanced Lua Topics - Coroutines

Bubba's Photo Bubba 06 May 2013

Although I have kept the old tutorial content here, I would suggest that you read the tutorial here instead. It is in a far more readable form, and I have revised a fair amount of it. If you prefer it in PDF form, you can download a copy from this link (Google Docs messed up some formatting, but it's still readable). An HTML version be found here.

Spoiler

Edited by Bubba, 08 May 2013 - 07:42 PM.
Quote

Dlcruz129's Photo Dlcruz129 06 May 2013

Awesome! Very in-depth.
Quote

Sammich Lord's Photo Sammich Lord 06 May 2013

Instant +1. I hardly +1 anybody. I love every one of your tutorials.
Quote

Bubba's Photo Bubba 06 May 2013

Thanks guys! I appreciate it.
Quote

superaxander's Photo superaxander 06 May 2013

I love it. I already knew everything you explained. But it still gave me a fresh look at coroutines
Quote

Molinko's Photo Molinko 07 May 2013

This tutorial is fantastic!!
- I love your tutorials Bubba. Also, would you consider making a tutorial of this depth for metatables??
I always learn a lot from these in depth tuts' and yours are the best, in my opinion. I would love to see one for metatables!!
- Thank you
Quote

Bubba's Photo Bubba 07 May 2013

View PostMolinko, on 07 May 2013 - 03:09 PM, said:

This tutorial is fantastic!!
- I love your tutorials Bubba. Also, would you consider making a tutorial of this depth for metatables??
I always learn a lot from these in depth tuts' and yours are the best, in my opinion. I would love to see one for metatables!!
- Thank you

Hi there Molinko. I would be happy to do a tutorial on metatables. I've been planning to do a video on them, but I'm not so certain that videos are the best way to go about it anymore. I'm better at writing and revising than I am at recording.

Anyway, thank you for the praise! It's really encouraging :D
Quote

Lyqyd's Photo Lyqyd 07 May 2013

This is an excellent tutorial, but it is in dire need of the explanation that os.pullEvent is a wrapper that calls coroutine.yield. It also happens to interact with the return values according to the "events" convention that ComputerCraft uses. I feel like there's a bit too much "magic" surrounding os.pullEvent at this point and that it would be highly valuable to dive into how and why os.pullEvent works.

I also upvoted the OP, which is not something I often do. :)
Quote

SadKingBilly's Photo SadKingBilly 07 May 2013

View PostBubba, on 07 May 2013 - 04:28 PM, said:

[...] I would be happy to do a tutorial on metatables. I've been planning to do a video on them, but I'm not so certain that videos are the best way to go about it anymore. I'm better at writing and revising than I am at recording. [...]
But you have the perfect voice for recording! I don't mean to be creepy, it's just really rare to find someone whose voice is both understandable and tolerable. Even though I'd prefer text tutorials, it feels like a shame not to be recording your voice. :P

Anyway, this is a great tutorial, definitely coming back to it when I feel brave enough to try the more advanced stuff. Have you considered doing a tutorial on patterns and captures?
Quote

Hawk777's Photo Hawk777 07 May 2013

You missed a couple of return values from status: running (if it is the currently running coroutine) and normal (if it is an ancestor, or superior as you call it, of the current coroutine).
Quote

Bubba's Photo Bubba 07 May 2013

View PostLyqyd, on 07 May 2013 - 04:48 PM, said:

This is an excellent tutorial, but it is in dire need of the explanation that os.pullEvent is a wrapper that calls coroutine.yield. It also happens to interact with the return values according to the "events" convention that ComputerCraft uses. I feel like there's a bit too much "magic" surrounding os.pullEvent at this point and that it would be highly valuable to dive into how and why os.pullEvent works.

I also upvoted the OP, which is not something I often do. :)

To be honest, I hadn't looked into the logic behind os.pullEvent (now I understand why pullEvent/yield behave the same). Thanks for that Lyqyd :) I'll add it in.

View PostSadKingBilly, on 07 May 2013 - 04:57 PM, said:

View PostBubba, on 07 May 2013 - 04:28 PM, said:

[...] I would be happy to do a tutorial on metatables. I've been planning to do a video on them, but I'm not so certain that videos are the best way to go about it anymore. I'm better at writing and revising than I am at recording. [...]
But you have the perfect voice for recording! I don't mean to be creepy, it's just really rare to find someone whose voice is both understandable and tolerable. Even though I'd prefer text tutorials, it feels like a shame not to be recording your voice. :P

Anyway, this is a great tutorial, definitely coming back to it when I feel brave enough to try the more advanced stuff. Have you considered doing a tutorial on patterns and captures?
Heh, thanks :) A tutorial on patterns would be kind of fun - I'll look into it whenever I finish with metatables. Voice recording is difficult to do, but I'll consider doing text and voice and cover all my bases.

View PostHawk777, on 07 May 2013 - 06:23 PM, said:

You missed a couple of return values from status: running (if it is the currently running coroutine) and normal (if it is an ancestor, or superior as you call it, of the current coroutine).

Thanks. Forgot about those. I'll add them in.
Quote

Bubba's Photo Bubba 08 May 2013

Well I've completely revised the tutorial and posted it to Google Docs. In my opinion it is much more readable, but if you guys think it looks better the old way let me know and I'll transfer the content over to the forum post.
Quote

darkrising's Photo darkrising 11 May 2013

This has helped me a great deal, thank you for writing this. :P
Quote

Zudo's Photo Zudo 09 Jul 2013

Thanks so much!!
Quote

steel_toed_boot's Photo steel_toed_boot 20 Jul 2013

If you want a real solid example of the power of coroutines, look through the parallel API provided through Computercraft.

Spoiler
Quote

surferpup's Photo surferpup 11 Jan 2014

I read through this and tried the example. I have a couple of questions:

First, I didn't notice any arguments accepted by either the getChars() function or the saveChars() function. However, you call it as follows:

coroutine.resume(getC,unpack(evt))

How does the unpack(evt) argument affect this?

Second, I didn't notice any yield statement in either coroutine, so I am struggling to understand how this actually works (I know it does work, because I ran the code and it worked).

Could someone clarify that for me? Thank you.
Quote

Lyqyd's Photo Lyqyd 11 Jan 2014

They both yield with os.pullEvent(). os.pullEvent calls os.pullEventRaw, which in turn calls coroutine.yield.
Quote

surferpup's Photo surferpup 11 Jan 2014

Thanks Lyqyd. That makes sense.. However, I am not following how unpack(evt) is passed to getChars():

View Postsurferpup, on 11 January 2014 - 05:53 PM, said:

I didn't notice any arguments accepted by either the getChars() function or the saveChars() function. However, you call it as follows:

coroutine.resume(getC,unpack(evt))

How does the unpack(evt) argument affect this?

Can anyone explain that?
Edited by surferpup, 11 January 2014 - 06:16 PM.
Quote

Lyqyd's Photo Lyqyd 11 Jan 2014

Oh, he has the event stored in a table called evt. To get it back out into multiple return values, he needs to unpack it. So, for instance:

If our event was:

"monitor_touch", "left", 3, 4

coroutine.resume(getC, evt) would mean that the os.pullEvent() would get this as its return value:

{"monitor_touch", "left", 3, 4}

Note that that is just a single table, taking up one argument. Instead, unpack splits the table out into individual return values again instead of a single table.

"monitor_touch", "left", 3, 4
Quote

surferpup's Photo surferpup 11 Jan 2014

Nevermind -- I answered my own question. There is a difference between the version of the tutorial in the spoilers and the version posted on google docs. The spoiler version is more up-to-date. The spoiler section titled "But what about events? How do I capture them?" addresses this exact scenario. As I understand it, essentially, the coroutine has yielded on it's os.pullEvent(). When the coroutine is resumed, it is passed the event from the main loop with the unpack(evt) argument.

Thanks for the great tutorial and the clarifications. Now I have to go and rework a whole bunch of code to take advantage of coroutines. Powerful stuff.

And thanks Lyqyd for the better explanation -- I get it. I love complexity one can achieve with the simplicity of Lua.
Edited by surferpup, 11 January 2014 - 06:57 PM.
Quote