<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Co-routines as an alternative to state machines</title>
	<atom:link href="http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/feed/" rel="self" type="application/rss+xml" />
	<link>http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/</link>
	<description>Eli Bendersky's personal website</description>
	<lastBuildDate>Wed, 10 Mar 2010 17:32:25 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: José Hérnandez</title>
		<link>http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/comment-page-1/#comment-203226</link>
		<dc:creator>José Hérnandez</dc:creator>
		<pubDate>Fri, 04 Sep 2009 15:23:36 +0000</pubDate>
		<guid isPermaLink="false">http://eli.thegreenplace.net/?p=1905#comment-203226</guid>
		<description>@Roger: I think Eli makes a nice argument for coroutines. When one thinks about parsing, one would first imagine the code to parse the input without having to record the results in the middle of parsing. Coroutine parsers are written with this kind of frame of mind. If one writes a parser that just burns through the input without returning any of the parsed results, it would look strikingly like a parser written with coroutines. It&#039;s this natural approach that I believe Eli finds appealing.</description>
		<content:encoded><![CDATA[<p>@Roger: I think Eli makes a nice argument for coroutines. When one thinks about parsing, one would first imagine the code to parse the input without having to record the results in the middle of parsing. Coroutine parsers are written with this kind of frame of mind. If one writes a parser that just burns through the input without returning any of the parsed results, it would look strikingly like a parser written with coroutines. It&#8217;s this natural approach that I believe Eli finds appealing.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: roger rubygems</title>
		<link>http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/comment-page-1/#comment-203000</link>
		<dc:creator>roger rubygems</dc:creator>
		<pubDate>Thu, 03 Sep 2009 23:04:58 +0000</pubDate>
		<guid isPermaLink="false">http://eli.thegreenplace.net/?p=1905#comment-203000</guid>
		<description>Thanks good writeup.  I&#039;m not so sure about your conclusion, however...How would it look comparison-wise if you had 10 states that all called each other, complexity-wise?

Being able to pipeline operations together seems to be a good fit for coroutines, as mentioned.  Or using them to allow for functional programming in an evented architecture :)
Cheers.

-r</description>
		<content:encoded><![CDATA[<p>Thanks good writeup.  I&#8217;m not so sure about your conclusion, however&#8230;How would it look comparison-wise if you had 10 states that all called each other, complexity-wise?</p>
<p>Being able to pipeline operations together seems to be a good fit for coroutines, as mentioned.  Or using them to allow for functional programming in an evented architecture <img src='http://eli.thegreenplace.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Cheers.</p>
<p>-r</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: eliben</title>
		<link>http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/comment-page-1/#comment-201266</link>
		<dc:creator>eliben</dc:creator>
		<pubDate>Mon, 31 Aug 2009 03:35:32 +0000</pubDate>
		<guid isPermaLink="false">http://eli.thegreenplace.net/?p=1905#comment-201266</guid>
		<description>@Ryan,

Just to put things straight, I&#039;m not coming out against state machines here. State machines are an important tool - they definitely have their place in software. I&#039;m just presenting co-routines as an alternative for certain cases.

Explicitly specifying state machines is indeed better than just hand coding them from a diagram. There are nice tools out there, like Ragel, that even compile an FSM in some simple DSL to real code (C, C++, Java, Ruby - unfortunately no Python).</description>
		<content:encoded><![CDATA[<p>@Ryan,</p>
<p>Just to put things straight, I&#8217;m not coming out against state machines here. State machines are an important tool &#8211; they definitely have their place in software. I&#8217;m just presenting co-routines as an alternative for certain cases.</p>
<p>Explicitly specifying state machines is indeed better than just hand coding them from a diagram. There are nice tools out there, like Ragel, that even compile an FSM in some simple DSL to real code (C, C++, Java, Ruby &#8211; unfortunately no Python).</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: James Thiele</title>
		<link>http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/comment-page-1/#comment-201265</link>
		<dc:creator>James Thiele</dc:creator>
		<pubDate>Mon, 31 Aug 2009 03:35:22 +0000</pubDate>
		<guid isPermaLink="false">http://eli.thegreenplace.net/?p=1905#comment-201265</guid>
		<description>The basic correspondence between the Python implementations of state machines in coroutines and &quot;regular&quot; state machines is that each (yield) in the coroutine corresponds to a state in the state machine. You assert that a state machine with 20 states would be difficult to follow. I doubt that a function with 20 (yield)s would be any easier.</description>
		<content:encoded><![CDATA[<p>The basic correspondence between the Python implementations of state machines in coroutines and &#8220;regular&#8221; state machines is that each (yield) in the coroutine corresponds to a state in the state machine. You assert that a state machine with 20 states would be difficult to follow. I doubt that a function with 20 (yield)s would be any easier.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ryan Fox</title>
		<link>http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/comment-page-1/#comment-201083</link>
		<dc:creator>Ryan Fox</dc:creator>
		<pubDate>Sun, 30 Aug 2009 20:32:55 +0000</pubDate>
		<guid isPermaLink="false">http://eli.thegreenplace.net/?p=1905#comment-201083</guid>
		<description>For the tree traversal, I won&#039;t argue that the recursive version is simpler, but if you did implement it with an explicit stack, you could then very easily implement a breadth-first traversal by replacing the stack with a queue.</description>
		<content:encoded><![CDATA[<p>For the tree traversal, I won&#8217;t argue that the recursive version is simpler, but if you did implement it with an explicit stack, you could then very easily implement a breadth-first traversal by replacing the stack with a queue.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ryan Fox</title>
		<link>http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/comment-page-1/#comment-201079</link>
		<dc:creator>Ryan Fox</dc:creator>
		<pubDate>Sun, 30 Aug 2009 20:28:25 +0000</pubDate>
		<guid isPermaLink="false">http://eli.thegreenplace.net/?p=1905#comment-201079</guid>
		<description>I agree that state machines as nested conditions is hard to comprehend when the complexity increases, but have you considered an explicit state machine model?

http://www.perl.com/pub/a/2004/09/23/fsms.html
This article (written for Perl, but should be easy to understand) demonstrates this. The code just above the &quot;Final Assembly&quot; heading shows a nice example of an explicit state machine. You essentially build a table of [state, condition, action] to define the behaviour.

Another benefit of this style of implementation is that it&#039;s very easy to parse and then give to dot http://www.graphviz.org/ to draw a visual representation of the state machine.</description>
		<content:encoded><![CDATA[<p>I agree that state machines as nested conditions is hard to comprehend when the complexity increases, but have you considered an explicit state machine model?</p>
<p><a href="http://www.perl.com/pub/a/2004/09/23/fsms.html" rel="nofollow">http://www.perl.com/pub/a/2004/09/23/fsms.html</a><br />
This article (written for Perl, but should be easy to understand) demonstrates this. The code just above the &#8220;Final Assembly&#8221; heading shows a nice example of an explicit state machine. You essentially build a table of [state, condition, action] to define the behaviour.</p>
<p>Another benefit of this style of implementation is that it&#8217;s very easy to parse and then give to dot <a href="http://www.graphviz.org/" rel="nofollow">http://www.graphviz.org/</a> to draw a visual representation of the state machine.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: eliben</title>
		<link>http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/comment-page-1/#comment-200927</link>
		<dc:creator>eliben</dc:creator>
		<pubDate>Sun, 30 Aug 2009 15:02:41 +0000</pubDate>
		<guid isPermaLink="false">http://eli.thegreenplace.net/?p=1905#comment-200927</guid>
		<description>&lt;strong&gt;Ludvig,&lt;/strong&gt;

I haven&#039;t tried benchmarking, but in Dave Beazley&#039;s article he came to the conclusion that co-routines are more efficient than the alternative.

&lt;strong&gt;BC,&lt;/strong&gt;

Thanks, this is very interesting.</description>
		<content:encoded><![CDATA[<p><strong>Ludvig,</strong></p>
<p>I haven&#8217;t tried benchmarking, but in Dave Beazley&#8217;s article he came to the conclusion that co-routines are more efficient than the alternative.</p>
<p><strong>BC,</strong></p>
<p>Thanks, this is very interesting.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: eliben</title>
		<link>http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/comment-page-1/#comment-200923</link>
		<dc:creator>eliben</dc:creator>
		<pubDate>Sun, 30 Aug 2009 15:00:39 +0000</pubDate>
		<guid isPermaLink="false">http://eli.thegreenplace.net/?p=1905#comment-200923</guid>
		<description>&lt;strong&gt;Brian,&lt;/strong&gt;
Here&#039;s Python-pseudocode for inorder traversal of a binary tree:

`&lt;code&gt;def traverse(node, func):&lt;br /&gt;
  if node is None:&lt;br /&gt;
    return&lt;br /&gt;
  traverse(node__abENT__#46;left)&lt;br /&gt;
  func(node)&lt;br /&gt;
  traverse(node__abENT__#46;right)&lt;/code&gt;`

I challenge you to write it in a more readable way using explicit stacks instead of recursion.
</description>
		<content:encoded><![CDATA[<p><strong>Brian,</strong><br />
Here&#8217;s Python-pseudocode for inorder traversal of a binary tree:</p>
<div class="backtick"><pre><code>def traverse(node, func):
  if node is None:
    return
  traverse(node&#46;left)
  func(node)
  traverse(node&#46;right)</code></pre></div>
<p>I challenge you to write it in a more readable way using explicit stacks instead of recursion.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ludvig Ericson</title>
		<link>http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/comment-page-1/#comment-200910</link>
		<dc:creator>Ludvig Ericson</dc:creator>
		<pubDate>Sun, 30 Aug 2009 14:34:12 +0000</pubDate>
		<guid isPermaLink="false">http://eli.thegreenplace.net/?p=1905#comment-200910</guid>
		<description>Well-written, nice and informative. Good language use, and a very interesting subject.

However, have you looked at the performance implications, if any? It somehow feels like there&#039;d be a price to pay for this.</description>
		<content:encoded><![CDATA[<p>Well-written, nice and informative. Good language use, and a very interesting subject.</p>
<p>However, have you looked at the performance implications, if any? It somehow feels like there&#8217;d be a price to pay for this.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: BC</title>
		<link>http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/comment-page-1/#comment-200810</link>
		<dc:creator>BC</dc:creator>
		<pubDate>Sun, 30 Aug 2009 09:16:14 +0000</pubDate>
		<guid isPermaLink="false">http://eli.thegreenplace.net/?p=1905#comment-200810</guid>
		<description>python co-routines are a killer feature for scientific data-acquisition or instrumentation applications. Traditionally, this type of app makes extensive use of state-machines to control the interaction with external hardware. We&#039;ve just finished a somewhat complex instrument application where we&#039;ve used coroutines extensive and it&#039;s been a huge success.

We normally use data-acquisition devices (PCI cards, from National Instruments) to generate and collect analog and digital signals. These feed a &quot;pipeline&quot; of co-routines. The data processing pipeline can comprise elements like &quot;data averaging&quot;, &quot;output-to-file&quot;, &quot;plotting&quot; and also hardware interactions such as moving linear actuators and GPIB devices. Each one gets a coroutine to control it and manage it&#039;s state.

The data acquisition pipeline node looks like:
`&lt;code&gt;@pipeline
def daq_lifecycle(self, output):
__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;task = daq__abENT__#46;initialiseTask()
__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;task__abENT__#46;start()
__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;try:
__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;while True:
__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;output__abENT__#46;send((yield))
__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;finally:
__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;task__abENT__#46;clear()&lt;/code&gt;`
where the &#039;daq&#039; object represents the PCI card device (wrapped with ctypes). 

We also have:
`&lt;code&gt;# a little decorator to __abENT__apos;ping__abENT__apos; the coroutines first __abENT__#46;next() call
def pipeline(func):
__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;def wrapper(*args, **kw):
__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;gen = func(*args, **kw)
__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;gen__abENT__#46;next()
__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;__abENT__#46;return gen&lt;/code&gt;`
When new data arrives, it&#039;s is &quot;sent&quot; into the pipeline (in a callback called by the device drivers whenever new data is available). Each node in the pipeline is given an output-coroutine to send it&#039;s data into (except for the terminating node). A full pipeline is built by joining all the required nodes together. 

One cool feature is the use of try-finally block. If there&#039;s an exception downstream in the pipeline, it propagates upwards and all the finally blocks execute, restoring the hardware to a safe state. The pipeline can be shutdown manually by &quot;throw&quot;ing an exception into it. The downstream nodes are automatically garbage-collected and all their finally blocks execute, ensuring a safe final state.

Using co-routines means we can drastically reduce the number of state-maintaining attributes on the objects, which simplifies the code and reduces the opportunities for bugs. Also, describing state in terms of point-of-executing in the code makes the state evolution or lifecycle intuitive to understand.

python is awesome.</description>
		<content:encoded><![CDATA[<p>python co-routines are a killer feature for scientific data-acquisition or instrumentation applications. Traditionally, this type of app makes extensive use of state-machines to control the interaction with external hardware. We&#8217;ve just finished a somewhat complex instrument application where we&#8217;ve used coroutines extensive and it&#8217;s been a huge success.</p>
<p>We normally use data-acquisition devices (PCI cards, from National Instruments) to generate and collect analog and digital signals. These feed a &#8220;pipeline&#8221; of co-routines. The data processing pipeline can comprise elements like &#8220;data averaging&#8221;, &#8220;output-to-file&#8221;, &#8220;plotting&#8221; and also hardware interactions such as moving linear actuators and GPIB devices. Each one gets a coroutine to control it and manage it&#8217;s state.</p>
<p>The data acquisition pipeline node looks like:<br />
<code class="backtick">@pipeline<br />
def daq_lifecycle(self, output):<br />
&#46;&#46;&#46;&#46;task = daq&#46;initialiseTask()<br />
&#46;&#46;&#46;&#46;&#46;&#46;&#46;&#46;task&#46;start()<br />
&#46;&#46;&#46;&#46;try:<br />
&#46;&#46;&#46;&#46;&#46;&#46;&#46;&#46;while True:<br />
&#46;&#46;&#46;&#46;&#46;&#46;&#46;&#46;&#46;&#46;&#46;&#46;output&#46;send((yield))<br />
&#46;&#46;&#46;&#46;finally:<br />
&#46;&#46;&#46;&#46;&#46;&#46;&#46;&#46;task&#46;clear()</code><br />
where the &#8216;daq&#8217; object represents the PCI card device (wrapped with ctypes). </p>
<p>We also have:<br />
<code class="backtick"># a little decorator to &#039;ping&#039; the coroutines first &#46;next() call<br />
def pipeline(func):<br />
&#46;&#46;&#46;&#46;def wrapper(*args, **kw):<br />
&#46;&#46;&#46;&#46;&#46;&#46;&#46;&#46;gen = func(*args, **kw)<br />
&#46;&#46;&#46;&#46;&#46;&#46;&#46;&#46;gen&#46;next()<br />
&#46;&#46;&#46;&#46;&#46;&#46;&#46;&#46;return gen</code><br />
When new data arrives, it&#8217;s is &#8220;sent&#8221; into the pipeline (in a callback called by the device drivers whenever new data is available). Each node in the pipeline is given an output-coroutine to send it&#8217;s data into (except for the terminating node). A full pipeline is built by joining all the required nodes together. </p>
<p>One cool feature is the use of try-finally block. If there&#8217;s an exception downstream in the pipeline, it propagates upwards and all the finally blocks execute, restoring the hardware to a safe state. The pipeline can be shutdown manually by &#8220;throw&#8221;ing an exception into it. The downstream nodes are automatically garbage-collected and all their finally blocks execute, ensuring a safe final state.</p>
<p>Using co-routines means we can drastically reduce the number of state-maintaining attributes on the objects, which simplifies the code and reduces the opportunities for bugs. Also, describing state in terms of point-of-executing in the code makes the state evolution or lifecycle intuitive to understand.</p>
<p>python is awesome.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
