Version 7 of lies and oversimplifications

Updated 2010-06-03 14:29:18 by AMG

jblz: When i was in fourth grade, my science teacher told us that electrons rotate around the nucleus of an atom like planets rotate around the sun. At the end of class, he noted that he was lying, and that in fact electrons didn't really do that, but that was just a way for us to begin to understand it. I got home that day and immediately went crying hysterically to my dad, "THEY'RE LYING TO US ABOUT ATOMS! ATOMS ARE SO IMPORTANT!"

Lars H: Cf. http://en.wikipedia.org/wiki/Lie-to-children

AMG: And here's the opposite of lying to children: [L1 ]


(A footnote to Coroutines for the Dazed and Confused)

Coroutines: coroutines are the first thing in tcl to ever confuse me to the point of utter incomprehension. {*} made me scratch my head for a minute, but then the light bulb went off. we need some really easy-reader level explanation of them A) because they can be difficult to grasp conceptually (wikipedia helped with this quite a bit) B) Even after understanding the pseudo-code on wikipedia on the topic, the implementation can be difficult to follow.

I think something needs to emphasize the "command aliasing" aspect of the coroutine command, clearly and simply communicate the order in which commands are executed, and simply explain the operation of the yield command, even if it requires "lies and oversimplifications" at first. All the current explanations were far too robust and complex for me to understand.

AMG: Let me give it a try. I'll put the names of the principal commands in bold, to maybe help highlight what creates what and what calls what.

When you call [coroutine], you tell it two things: the name of a new command to be created, and an existing command to run, including arguments. Let's say the new command is to be named [resume] and the existing command is [procedure]. [coroutine] runs [procedure] until it returns or yields, and the returned/yielded value is returned by [coroutine]. In this sense, it's like simply calling [procedure] directly.

Here's where things get different. If [procedure] happened to yield, then the [resume] command is created. When [procedure] yielded, it basically got frozen in time, taken off the call stack but ready to be put back into action. Calling [resume] continues execution of [procedure] right where it left off, until it returns or yields again.

Inside [procedure], [yield] returns the (optional) argument that was passed to [resume]. Inside the caller, [resume] returns the value that was returned or yielded by [procedure].

The [resume] command continues to exist so long as [procedure] yields, then it finally goes away when [procedure] returns.

Throwing and erroring are also considered returning. Yielding is distinct from returning in that it does not terminate execution, only pauses it.

Here's another way to look at it. The arguments to [coroutine] are as follows, but not in this order:

  • The procedure to carry out
  • A handle used to resume the procedure after it yields

I'm not sure what you mean by "command aliasing", unless you're trying to say that [resume] becomes an alias for [procedure]. I don't think this is the right way to look at things. [procedure] is a library routine like any other, waiting to be called, whereas [resume] is an in-progress execution of [procedure] that just happens to be paused at the moment. And if [procedure] isn't currently in progress but paused, [resume] doesn't exist.

I hope this helps!

Hmm, actually I'm afraid this might be the kind of too-robust explanation you can't absorb all at once. Let me try again.

[coroutine] runs a command of your choice (let's say [procedure]) and returns its result. If [procedure] happens to yield instead of returning, [coroutine] creates a new command whose name you get to pick (here, [resume]). When you invoke [resume], [procedure] starts running again exactly at the point that it yielded. In fact, [yield] returns to [procedure] whatever argument you passed to [resume]. Similarly, [resume] returns whatever argument was passed to [yield]. [resume] can be used repeatedly, until [procedure] returns instead of yields, and then [resume] is deleted.

Basically, you have two threads of execution, except that instead of running at the same time, they're taking turns. The [yield] and [resume] commands are used to switch between them and pass data from one to the other.

Read this, write some code, then read my previous explanation. :^)


everything is a string: discuss :)