{"id":62,"date":"2015-05-16T00:25:04","date_gmt":"2015-05-16T05:25:04","guid":{"rendered":"http:\/\/www.playwithlua.com\/?p=62"},"modified":"2020-05-22T14:04:16","modified_gmt":"2020-05-22T19:04:16","slug":"iterators","status":"publish","type":"post","link":"http:\/\/www.playwithlua.com\/?p=62","title":{"rendered":"Iterators"},"content":{"rendered":"<p>Lua doesn&#8217;t have a lot of control structures. There&#8217;s the obvious <code>if<\/code> statement, the <code>while<\/code> loop and <code>repeat<\/code>\/<code>until<\/code> loop, and the <code>for<\/code> loop. Mostly, the <code>for<\/code> gets used to iterate over tables:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">t <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span><span style=\"color: #ff6666;\">'a'<\/span><span style=\"color: #66cc66;\">,<\/span><span style=\"color: #ff6666;\">'b'<\/span><span style=\"color: #66cc66;\">,<\/span><span style=\"color: #ff6666;\">'c'<\/span><span style=\"color: #66cc66;\">,<\/span><span style=\"color: #ff6666;\">'d'<\/span><span style=\"color: #66cc66;\">,<\/span><span style=\"color: #ff6666;\">'e'<\/span><span style=\"color: #66cc66;\">&#125;<\/span>\n&nbsp;\n<span style=\"color: #aa9900; font-weight: bold;\">for<\/span> i<span style=\"color: #66cc66;\">,<\/span> v <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> <span style=\"color: #0000aa;\">ipairs<\/span><span style=\"color: #66cc66;\">&#40;<\/span>t<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n  <span style=\"color: #0000aa;\">print<\/span><span style=\"color: #66cc66;\">&#40;<\/span>i<span style=\"color: #66cc66;\">,<\/span>t<span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>It&#8217;s annoying to have to remember to type <code>ipairs<\/code> every time. I&#8217;ve forgotten more than once. But, that minor annoyance is a good trade for the benefit of what the <code>for<\/code> statement actually does: generic iteration.<br \/>\n<!--more--><\/p>\n<h2>What&#8217;s an iterator?<\/h2>\n<p>The <code>for<\/code> statement isn&#8217;t just used for looping across tables, it loops through any sort of sequence represented by an iterator. An iterator in Lua is any function that conforms to a certain interface, and a lot of problems can be made simpler by writing your own iterators, instead of just using <code>pairs<\/code> and <code>ipairs<\/code>.<\/p>\n<p>Let&#8217;s look at a standard loop:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">t <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span>a<span style=\"color: #66cc66;\">=<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">,<\/span> b<span style=\"color: #66cc66;\">=<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">,<\/span> c<span style=\"color: #66cc66;\">=<\/span><span style=\"color: #cc66cc;\">3<\/span><span style=\"color: #66cc66;\">,<\/span> d<span style=\"color: #66cc66;\">=<\/span><span style=\"color: #cc66cc;\">4<\/span><span style=\"color: #66cc66;\">&#125;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">for<\/span> k<span style=\"color: #66cc66;\">,<\/span> v <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> <span style=\"color: #0000aa;\">pairs<\/span><span style=\"color: #66cc66;\">&#40;<\/span>t<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n  <span style=\"color: #0000aa;\">print<\/span><span style=\"color: #66cc66;\">&#40;<\/span>k<span style=\"color: #66cc66;\">,<\/span> v<span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>This is using the standard library iterator <code>pairs<\/code>. Let&#8217;s take a look at what that call to <code>pairs<\/code> actually returns:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #0000aa;\">pairs<\/span><span style=\"color: #66cc66;\">&#40;<\/span>t<span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #808080; font-style: italic;\">-- function: 0x418590    table: 0x141b600    nil<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Not to keep you in suspense, the table it returns is <code>t<\/code> itself, and the function is the builtin function <code>next<\/code>. What <code>next<\/code> does is take a table and a key in the table, and return the &#8220;next&#8221; key \/ value. It&#8217;s guaranteed to go over all the keys, in no particular order:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>t<span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #aa9900;\">nil<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #808080; font-style: italic;\">-- c    3<\/span>\n<span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>t<span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #ff6666;\">'c'<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #808080; font-style: italic;\">-- b    2<\/span>\n<span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>t<span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #ff6666;\">'b'<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #808080; font-style: italic;\">-- a    1<\/span>\n<span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>t<span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #ff6666;\">'a'<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #808080; font-style: italic;\">-- d    4<\/span>\n<span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>t<span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #ff6666;\">'d'<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #808080; font-style: italic;\">-- nil<\/span><\/pre><\/div><\/div><\/div>\n\n<p>So let&#8217;s write that original <code>for<\/code> loop in a more explicit way:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">for<\/span> k<span style=\"color: #66cc66;\">,<\/span> v <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> <span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">,<\/span> t<span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #aa9900;\">nil<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n  <span style=\"color: #0000aa;\">print<\/span><span style=\"color: #66cc66;\">&#40;<\/span>k<span style=\"color: #66cc66;\">,<\/span> v<span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Try it, it does the same thing. In fact, if you just want to go over part of the table, you can pass in an initial argument for <code>next<\/code>:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">for<\/span> k<span style=\"color: #66cc66;\">,<\/span> v <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> <span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">,<\/span> t<span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #ff6666;\">'b'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n  <span style=\"color: #0000aa;\">print<\/span><span style=\"color: #66cc66;\">&#40;<\/span>k<span style=\"color: #66cc66;\">,<\/span> v<span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>That will print out just the &#8216;a&#8217; and &#8216;d&#8217; keys (yours may vary; <code>next<\/code> iterates in an arbitrary order). That&#8217;s all the <code>for<\/code> statement does: it takes a function, an &#8220;invariant&#8221; first argument (the table), and an initial second argument. It calls the function repeatedly, making the second argument of each call be the first return value of the previous call, until the function returns <code>nil<\/code>.<\/p>\n<h2>Making an iterator<\/h2>\n<p>With that in mind, we can write our own iterators. Here&#8217;s one that loops over members of the triangular series:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">function<\/span> triangular<span style=\"color: #66cc66;\">&#40;<\/span>_<span style=\"color: #66cc66;\">,<\/span> n<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> <span style=\"color: #aa9900; font-weight: bold;\">not<\/span> n <span style=\"color: #aa9900; font-weight: bold;\">then<\/span> n <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n    n <span style=\"color: #66cc66;\">=<\/span> n <span style=\"color: #66cc66;\">+<\/span> <span style=\"color: #cc66cc;\">1<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> n<span style=\"color: #66cc66;\">,<\/span> n <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #66cc66;\">&#40;<\/span>n<span style=\"color: #66cc66;\">+<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">\/<\/span> <span style=\"color: #cc66cc;\">2<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n&nbsp;\n<span style=\"color: #aa9900; font-weight: bold;\">for<\/span> n<span style=\"color: #66cc66;\">,<\/span> v <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> triangular <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n    <span style=\"color: #0000aa;\">print<\/span><span style=\"color: #66cc66;\">&#40;<\/span>v<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> n <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">10<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span> <span style=\"color: #aa9900; font-weight: bold;\">break<\/span> <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Since this iterator will never naturally end, we insert a <code>break<\/code> statement after a while.<\/p>\n<p>Note how easy calling the iterator is compared to writing it, not that writing it is very hard. This is pretty common with iterators; you spend some effort writing one in order to make the rest of the code simpler.<\/p>\n<h2>A more complex example: depth-first traversal<\/h2>\n<p>So let&#8217;s write some iterators that do actually-useful things, like traversing a tree. What we&#8217;d like to be able to do is visit every node of a tree, and get the value of that node and the path down to it from the root. For example:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">tree <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span>a <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span>p <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span>p <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span>l <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span>e <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span><span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span>\n             n <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span>t <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span><span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">&#125;<\/span>\n&nbsp;\n<span style=\"color: #aa9900; font-weight: bold;\">for<\/span> n<span style=\"color: #66cc66;\">,<\/span> path <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> dft<span style=\"color: #66cc66;\">&#40;<\/span>tree<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n  <span style=\"color: #0000aa;\">print<\/span><span style=\"color: #66cc66;\">&#40;<\/span>n<span style=\"color: #66cc66;\">,<\/span> inspect<span style=\"color: #66cc66;\">&#40;<\/span>path<span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>(I&#8217;m using <a onclick=\"javascript:pageTracker._trackPageview('\/outgoing\/github.com\/kikito\/inspect.lua');\"  href=\"https:\/\/github.com\/kikito\/inspect.lua\">inspect.lua<\/a> to print the path, a really handy library).<\/p>\n<p>This iterator is a little different from the other one: it has complex state, rather than just a single number, so we&#8217;ll have <code>dft<\/code> just return a function that keeps the state in a closure. You can do that; <code>for<\/code> doesn&#8217;t care if your invariant state is <code>nil<\/code>, it&#8217;ll still pass it in every time but you can just ignore it. So, here&#8217;s the code:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">function<\/span> dft<span style=\"color: #66cc66;\">&#40;<\/span>tree<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> value_stack <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span><span style=\"color: #66cc66;\">&#125;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> node_stack <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span><span style=\"color: #66cc66;\">&#125;<\/span>\n&nbsp;\n    <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> <span style=\"color: #aa9900; font-weight: bold;\">function<\/span><span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n        <span style=\"color: #808080; font-style: italic;\">-- These represent the current node:<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> value<span style=\"color: #66cc66;\">,<\/span> node <span style=\"color: #66cc66;\">=<\/span> value_stack<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #66cc66;\">#<\/span>value_stack<span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">,<\/span> node_stack<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #66cc66;\">#<\/span>node_stack<span style=\"color: #66cc66;\">&#93;<\/span>\n&nbsp;\n        <span style=\"color: #808080; font-style: italic;\">-- Now, to find the next node:<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> <span style=\"color: #aa9900; font-weight: bold;\">not<\/span> <span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node_stack<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n            <span style=\"color: #808080; font-style: italic;\">-- Node stack empty, push the root node:<\/span>\n            <span style=\"color: #0000aa;\">table.insert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>value_stack<span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>tree<span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n            <span style=\"color: #0000aa;\">table.insert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node_stack<span style=\"color: #66cc66;\">,<\/span> tree<span style=\"color: #66cc66;\">&#41;<\/span>\n&nbsp;\n        <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> <span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node<span style=\"color: #66cc66;\">&#91;<\/span>value<span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n            <span style=\"color: #808080; font-style: italic;\">-- Otherwise, if the current node has children, push them on to the stack:<\/span>\n            <span style=\"color: #0000aa;\">table.insert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>value_stack<span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node<span style=\"color: #66cc66;\">&#91;<\/span>value<span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n            <span style=\"color: #0000aa;\">table.insert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node_stack<span style=\"color: #66cc66;\">,<\/span> node<span style=\"color: #66cc66;\">&#91;<\/span>value<span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n&nbsp;\n        <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> <span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node<span style=\"color: #66cc66;\">,<\/span> value<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n            <span style=\"color: #808080; font-style: italic;\">-- Otherwise, if there's a right sibling, alter the stack to show it:<\/span>\n            value_stack<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #66cc66;\">#<\/span>value_stack<span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node<span style=\"color: #66cc66;\">,<\/span> value<span style=\"color: #66cc66;\">&#41;<\/span>\n&nbsp;\n        <span style=\"color: #aa9900; font-weight: bold;\">else<\/span>\n            <span style=\"color: #808080; font-style: italic;\">-- Otherwise, pop the stack and find the next node of our parent<\/span>\n            <span style=\"color: #aa9900; font-weight: bold;\">while<\/span> <span style=\"color: #aa9900;\">true<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n                <span style=\"color: #0000aa;\">table.remove<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node_stack<span style=\"color: #66cc66;\">&#41;<\/span>\n                <span style=\"color: #0000aa;\">table.remove<\/span><span style=\"color: #66cc66;\">&#40;<\/span>value_stack<span style=\"color: #66cc66;\">&#41;<\/span>\n&nbsp;\n                <span style=\"color: #808080; font-style: italic;\">-- Must be the end of the tree:<\/span>\n                <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> <span style=\"color: #aa9900; font-weight: bold;\">not<\/span> <span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node_stack<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span> <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> <span style=\"color: #aa9900;\">nil<\/span> <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n&nbsp;\n                <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> value<span style=\"color: #66cc66;\">,<\/span> node <span style=\"color: #66cc66;\">=<\/span> value_stack<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #66cc66;\">#<\/span>value_stack<span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">,<\/span> node_stack<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #66cc66;\">#<\/span>node_stack<span style=\"color: #66cc66;\">&#93;<\/span>\n                <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> <span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node<span style=\"color: #66cc66;\">,<\/span> value<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n                    value_stack<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #66cc66;\">#<\/span>value_stack<span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #0000aa;\">next<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node<span style=\"color: #66cc66;\">,<\/span> value<span style=\"color: #66cc66;\">&#41;<\/span>\n                    <span style=\"color: #aa9900; font-weight: bold;\">break<\/span>\n                <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n            <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n&nbsp;\n        <span style=\"color: #808080; font-style: italic;\">-- Return the top of the value stack, and the current value stack<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> value_stack<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #66cc66;\">#<\/span>value_stack<span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">,<\/span> value_stack\n    <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>This is pretty straightforward. We keep a stack of the node labels \/ values we&#8217;ve visited, going back up to the root. We start with empty stacks, and find the next node in the traversal:<\/p>\n<ul>\n<li>If the stacks are empty, the next node is the root.<\/li>\n<li>If the current node (top of the stacks) has children, the next node is the first child.<\/li>\n<li>If the current node has no children but a next sibling, then it&#8217;s next.<\/li>\n<li>Finally, if none of those are true, we go to the previous node and look for a next sibling there.<\/li>\n<\/ul>\n<p>After all that, the value stack has a path to the current node, so we return its value, and the value stack itself. When I run it as above, I get this:<\/p>\n<pre>\r\na\t{ \"a\" }\r\nn\t{ \"a\", \"n\" }\r\nt\t{ \"a\", \"n\", \"t\" }\r\np\t{ \"a\", \"p\" }\r\np\t{ \"a\", \"p\", \"p\" }\r\nl\t{ \"a\", \"p\", \"p\", \"l\" }\r\ne\t{ \"a\", \"p\", \"p\", \"l\", \"e\" }\r\n<\/pre>\n<h2>Coroutine iterators<\/h2>\n<p>But, doing it iteratively like that is somewhat of a pain. It&#8217;s more natural to traverse a tree recursively. But how do we recurse in an iterator?<\/p>\n<p>First, let&#8217;s write this as a coroutine. Forget about iterators for now, let&#8217;s just write a coroutine that will yield all the nodes \/ paths:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">stack <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span><span style=\"color: #66cc66;\">&#125;<\/span>\n&nbsp;\n<span style=\"color: #aa9900; font-weight: bold;\">function<\/span> traverse<span style=\"color: #66cc66;\">&#40;<\/span>node<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">for<\/span> k<span style=\"color: #66cc66;\">,<\/span> v <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> <span style=\"color: #0000aa;\">pairs<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n        <span style=\"color: #0000aa;\">table.insert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>stack<span style=\"color: #66cc66;\">,<\/span> k<span style=\"color: #66cc66;\">&#41;<\/span>\n        <span style=\"color: #0000aa;\">coroutine.yield<\/span><span style=\"color: #66cc66;\">&#40;<\/span>k<span style=\"color: #66cc66;\">,<\/span> stack<span style=\"color: #66cc66;\">&#41;<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> <span style=\"color: #0000aa;\">type<\/span><span style=\"color: #66cc66;\">&#40;<\/span>v<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'table'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n            traverse<span style=\"color: #66cc66;\">&#40;<\/span>v<span style=\"color: #66cc66;\">&#41;<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n        <span style=\"color: #0000aa;\">table.remove<\/span><span style=\"color: #66cc66;\">&#40;<\/span>stack<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n&nbsp;\nco <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #0000aa;\">coroutine.create<\/span><span style=\"color: #66cc66;\">&#40;<\/span>traverse<span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Then, we can call it like this:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">repeat<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> _<span style=\"color: #66cc66;\">,<\/span> node<span style=\"color: #66cc66;\">,<\/span> path <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #0000aa;\">coroutine.resume<\/span><span style=\"color: #66cc66;\">&#40;<\/span>co<span style=\"color: #66cc66;\">,<\/span> tree<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #0000aa;\">print<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node<span style=\"color: #66cc66;\">,<\/span> inspect<span style=\"color: #66cc66;\">&#40;<\/span>path<span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">until<\/span> <span style=\"color: #aa9900; font-weight: bold;\">not<\/span> node<\/pre><\/div><\/div><\/div>\n\n<p>(We pass in the same tree every time but that&#8217;s okay, because the argument is ignored every time after the first.)<\/p>\n<p>So, let&#8217;s now turn this general pattern into an iterator:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">function<\/span> co_dft<span style=\"color: #66cc66;\">&#40;<\/span>tree<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> stack <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span><span style=\"color: #66cc66;\">&#125;<\/span>\n&nbsp;\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> <span style=\"color: #aa9900; font-weight: bold;\">function<\/span> traverse<span style=\"color: #66cc66;\">&#40;<\/span>node<span style=\"color: #66cc66;\">&#41;<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">for<\/span> k<span style=\"color: #66cc66;\">,<\/span> v <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> <span style=\"color: #0000aa;\">pairs<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n            <span style=\"color: #0000aa;\">table.insert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>stack<span style=\"color: #66cc66;\">,<\/span> k<span style=\"color: #66cc66;\">&#41;<\/span>\n            <span style=\"color: #0000aa;\">coroutine.yield<\/span><span style=\"color: #66cc66;\">&#40;<\/span>k<span style=\"color: #66cc66;\">,<\/span> stack<span style=\"color: #66cc66;\">&#41;<\/span>\n            <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> <span style=\"color: #0000aa;\">type<\/span><span style=\"color: #66cc66;\">&#40;<\/span>v<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'table'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n                traverse<span style=\"color: #66cc66;\">&#40;<\/span>v<span style=\"color: #66cc66;\">&#41;<\/span>\n            <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n            <span style=\"color: #0000aa;\">table.remove<\/span><span style=\"color: #66cc66;\">&#40;<\/span>stack<span style=\"color: #66cc66;\">&#41;<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n&nbsp;\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> co <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #0000aa;\">coroutine.create<\/span><span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #aa9900; font-weight: bold;\">function<\/span><span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> traverse<span style=\"color: #66cc66;\">&#40;<\/span>tree<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">end<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n&nbsp;\n    <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> <span style=\"color: #aa9900; font-weight: bold;\">function<\/span><span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> _<span style=\"color: #66cc66;\">,<\/span> value<span style=\"color: #66cc66;\">,<\/span> stack <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #0000aa;\">coroutine.resume<\/span><span style=\"color: #66cc66;\">&#40;<\/span>co<span style=\"color: #66cc66;\">&#41;<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> value<span style=\"color: #66cc66;\">,<\/span> stack\n    <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>It&#8217;s a pretty simple transformation. Move everything into the local scope of the iterator, and return a function that&#8217;s a wrapper for <code>coroutine.resume<\/code>. We can do this to make an iterator out of any coroutine, actually. And now that it&#8217;s an iterator, we can call it just like the iterative version:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">for<\/span> node<span style=\"color: #66cc66;\">,<\/span> path <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> co_dft<span style=\"color: #66cc66;\">&#40;<\/span>tree<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n    <span style=\"color: #0000aa;\">print<\/span><span style=\"color: #66cc66;\">&#40;<\/span>node<span style=\"color: #66cc66;\">,<\/span> inspect<span style=\"color: #66cc66;\">&#40;<\/span>path<span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<h2>Iterators are powerful<\/h2>\n<p>So, that&#8217;s how iterators work. It&#8217;s more than just an awkward syntax for a <code>for<\/code> loop; it&#8217;s actually an incredibly powerful feature of Lua.<\/p>\n<p>As always, the code for this is <a onclick=\"javascript:pageTracker._trackPageview('\/outgoing\/gist.github.com\/randrews\/76adcf823139165000b4');\"  href=\"https:\/\/gist.github.com\/randrews\/76adcf823139165000b4\">available on Github<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lua doesn&#8217;t have a lot of control structures. There&#8217;s the obvious if statement, the while loop and repeat\/until loop, and the for loop. Mostly, the for gets used to iterate over tables: t = &#123;&#8217;a&#8217;,&#8217;b&#8217;,&#8217;c&#8217;,&#8217;d&#8217;,&#8217;e&#8217;&#125; &nbsp; for i, v in ipairs&#40;t&#41; do print&#40;i,t&#41; end It&#8217;s annoying to have to remember to type ipairs every time. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/posts\/62"}],"collection":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=62"}],"version-history":[{"count":0,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/posts\/62\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=62"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=62"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=62"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}