<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Fabulous Adventures In Coding : Recursion</title><link>http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx</link><description>Tags: Recursion</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Immutability in C# Part Seven: More on Binary Trees</title><link>http://blogs.msdn.com/ericlippert/archive/2007/12/19/immutability-in-c-part-seven-more-on-binary-trees.aspx</link><pubDate>Wed, 19 Dec 2007 23:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6809314</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>21</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/6809314.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=6809314</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Lots of good comments on my previous post. To briefly follow up:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;One of the downsides of immutable tree implementations is that usually the tree must be built from the leaves up, which is not always convenient. We'll look at implementations which hide this fact from the user in future posts. &lt;/LI&gt;&lt;/UL&gt;
&lt;UL&gt;
&lt;LI&gt;One smartypants pointed out that sure, this tree can have cycles -- if you have &lt;EM&gt;another&lt;/EM&gt; binary tree implementation that has cycles and then paste such a cyclic tree in. True; what I meant was that &lt;EM&gt;using only the stated implementation&lt;/EM&gt;, it's impossible to create a tree with cycles. If you are hell bent on making a bad tree, you can surely do that. Again, in a future post we'll have a tree which is built up by calling tree "mutating" operations, and those really will be guaranteed acyclic even in a world where there are other bad implementations hanging around.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;And finally, one reader correctly identified the problem with my recursive implementation of in-order iteration. A tree of maximum height h ends up allocating O(h) iterator objects. The recursive calls get O(h) deep. If h is very large, this could blow the call stack. And if the tree has n nodes, each with an average height of O(h), then iterating each node will require O(h) recursive calls apiece. Therefore the total time cost in calls for iterating the entire tree is O(n h).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;In a binary tree with n nodes, h is always between log n and n, so that means that this iterator has best case asymptotic performance of O(n log n) and worst case&amp;nbsp; of O(n&lt;SUP&gt;2&lt;/SUP&gt;) in time, and uses between O(log n) and O(n) in both call stack and heap space. That's pretty lousy.&lt;/P&gt;
&lt;P&gt;A better implementation would be to write a tree traversal algorithm which does not use recursion. &lt;A href="http://blogs.msdn.com/ericlippert/archive/2005/08/01/recursion-part-two-unrolling-a-recursive-function-with-an-explicit-stack.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2005/08/01/recursion-part-two-unrolling-a-recursive-function-with-an-explicit-stack.aspx"&gt;Use an explicit stack rather than the call stack:&lt;/A&gt;&lt;SPAN class=code&gt;&lt;/P&gt;
&lt;P&gt;public static IEnumerable&amp;lt;T&amp;gt; InOrder&amp;lt;T&amp;gt;(this IBinaryTree&amp;lt;T&amp;gt; tree)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IStack&amp;lt;IBinaryTree&amp;lt;T&amp;gt;&amp;gt; stack = Stack&amp;lt;IBinaryTree&amp;lt;T&amp;gt;&amp;gt;.Empty;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (IBinaryTree&amp;lt;T&amp;gt; current = tree; !current.IsEmpty || !stack.IsEmpty; current = current.Right)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (!current.IsEmpty)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stack = stack.Push(current);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; current = current.Left;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; current = stack.Peek();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stack = stack.Pop();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return current.Value;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;This consumes O(n) time, O(h) heap space, and O(1) call stack space. It is also &lt;STRONG&gt;painful&lt;/STRONG&gt; to read and analyze compared to the slow naive implementation. 
&lt;P&gt;I would very much like to add new syntax to a hypothetical future version of C# which would be a syntactic sugar for the code above. If, hypothetically, we were prioritizing features for unannounced future versions of C#, unfortunately that one would not be our highest priority, so I wouldn't expect it any time soon. &lt;A href="http://blogs.msdn.com/wesdyer/archive/2007/03/23/all-about-iterators.aspx" mce_href="http://blogs.msdn.com/wesdyer/archive/2007/03/23/all-about-iterators.aspx"&gt;My colleague Wes has written a great article that goes into more details about the problem above&lt;/A&gt; and ways we might solve it in the future, so check that out if you want the details. 
&lt;P&gt;I have the code for the next few blog posts written, but odds are good that I'm not going to have time to write the surrounding text until after the festive holiday season is over. I hope you have a wonderful time during the remainder of 2007 and we'll see you bright and early in 2008 for more fabulous adventures!&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6809314" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item><item><title>Immutability in C# Part Six: A Simple Binary Tree</title><link>http://blogs.msdn.com/ericlippert/archive/2007/12/18/immutability-in-c-part-six-a-simple-binary-tree.aspx</link><pubDate>Tue, 18 Dec 2007 22:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6798908</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/6798908.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=6798908</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;OK, we've gotten pretty good at this by now. A straightforward implementation of an immutable generic binary tree requires little comment on the basics. A binary tree is either empty, or a value, left tree and right tree:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public interface IBinaryTree&amp;lt;V&amp;gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool IsEmpty { get; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; V Value { get; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBinaryTree&amp;lt;V&amp;gt; Left { get; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBinaryTree&amp;lt;V&amp;gt; Right { get; }&lt;BR&gt;} &lt;/SPAN&gt;
&lt;P&gt;And our implementation has, as always, a singleton empty tree. One minor point is that unlike previous data structures, where the structure itself knew how to build more of the same, this one does not. There's no obvious "insert" operation in a binary tree, so we'll just leave it up to the implementer. (A binary tree is essentially defined by its &lt;EM&gt;shape&lt;/EM&gt;, not by the operations one can perform on it.) In this case, we'll just make a constructor:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public sealed class BinaryTree&amp;lt;V&amp;gt; : IBinaryTree&amp;lt;V&amp;gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private sealed class EmptyBinaryTree : IBinaryTree&amp;lt;V&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool IsEmpty { get { return true; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IBinaryTree&amp;lt;V&amp;gt; Left { get { throw new Exception("Empty tree"); } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IBinaryTree&amp;lt;V&amp;gt; Right { get { throw new Exception("Empty tree"); } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public V Value { get { throw new Exception("Empty tree"); } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static readonly EmptyBinaryTree empty = new EmptyBinaryTree();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IBinaryTree&amp;lt;V&amp;gt; Empty { get { return empty; } }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly V value;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IBinaryTree&amp;lt;V&amp;gt; left;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IBinaryTree&amp;lt;V&amp;gt; right; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool IsEmpty { get { return false; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public V Value { get { return value; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IBinaryTree&amp;lt;V&amp;gt; Left { get { return left; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IBinaryTree&amp;lt;V&amp;gt; Right { get { return right; } } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public BinaryTree(V value, IBinaryTree&amp;lt;V&amp;gt; left, IBinaryTree&amp;lt;V&amp;gt; right)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.value = value;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.left = left ?? Empty;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.right = right ?? Empty;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Note that another nice feature of immutable data structures is that &lt;STRONG&gt;it&lt;/STRONG&gt; &lt;STRONG&gt;is impossible to accidentally (or deliberately!) create a tree which contains a cycle&lt;/STRONG&gt;. In a mutable tree you could do something stupid like making the root a child of one of the leaves (or, for that matter, a child of itself!) Then you have to either live with the possibility that a user will create a cyclic "tree" and hope for the best (or, in other words, crash and/or hang) or you have to build yourself a cycle detector. Cycle detectors have potentially serious performance implications. It may be best to simply prevent the situation from arising in the first place.&lt;/P&gt;
&lt;P&gt;A feature conspicuous by its absence from the above implementation is enumeration. Unlike a stack or a queue, there's no obvious best order in which to enumerate the members a binary tree. First off, there's the question of whether to enumerate in depth-first or breadth-first order, and then the matter of whether the parent comes before, after or between the children.&lt;/P&gt;
&lt;P&gt;We could create extension methods which did various different enumerations on a binary tree. Here is a &lt;STRONG&gt;bad implementation&lt;/STRONG&gt; of an "in order" traversal (depth first, parent comes between the children -- so-called because in a binary search tree, this enumerates the nodes in sorted order.)&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public static IEnumerable&amp;lt;V&amp;gt; InOrder&amp;lt;V&amp;gt;(this IBinaryTree&amp;lt;V&amp;gt; tree)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // BAD IMPLEMENTATION, DO NOT DO THIS&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (tree.IsEmpty) yield break;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach(V v in tree.Left.InOrder()) yield return v;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return tree.Value;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach(V v in tree.Right.InOrder()) yield return v;&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;This &lt;EM&gt;seems&lt;/EM&gt; perfectly straightforward and sensible, but this implementation is actually quite flawed. We can do a lot better. What is wrong with this implementation of enumeration, and how would you fix it? (Hint: start your analysis with the assumption that the tree has maximum height h and total number of nodes n.)&lt;/P&gt;
&lt;P&gt;Next time: a better implementation of traversal, and then after that, some more complex kinds of immutable binary tree. &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6798908" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category></item><item><title>Why does a recursive lambda cause a definite assignment error?</title><link>http://blogs.msdn.com/ericlippert/archive/2006/08/18/why-does-a-recursive-lambda-cause-a-definite-assignment-error.aspx</link><pubDate>Fri, 18 Aug 2006 22:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:706398</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/706398.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=706398</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Hey fabulous readers, sorry for not much blogging lately. Between implementing LINQ and making plans to attend my first Burning Man, there's been no time for anything. We've had lots of new ideas generated here for the type inferencing algorithm which I will discuss in detail when I get back. &lt;/P&gt;
&lt;P&gt;For now, here's a question I got recently about definite assignment analysis and recursive functions. Clearly this is legal: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;delegate void Action&amp;lt;A&amp;gt;(A a);&lt;BR&gt;delegate void Traversal&amp;lt;T&amp;gt;(Tree&amp;lt;T&amp;gt; t, Action&amp;lt;T&amp;gt; a);&lt;BR&gt;&lt;BR&gt;static void DepthFirstTraversal&amp;lt;T&amp;gt;(Tree&amp;lt;T&amp;gt; t, Action&amp;lt;T&amp;gt; a){&lt;BR&gt;&amp;nbsp; if (t == null) return;&lt;BR&gt;&amp;nbsp; a(t.Value);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN class=code&gt;&amp;nbsp; DepthFirstTraversal(t.Left, a);&lt;BR&gt;&amp;nbsp; DepthFirstTraversal(t.Right, a);&lt;BR&gt;}&lt;BR&gt;static void Traverse&amp;lt;T&amp;gt;(Tree&amp;lt;T&amp;gt; t, Traversal&amp;lt;T&amp;gt; f, Action&amp;lt;T&amp;gt; a){&lt;BR&gt;&amp;nbsp; f(t, a);&lt;BR&gt;}&lt;BR&gt;static void Print&amp;lt;T&amp;gt;(T t){&lt;BR&gt;&amp;nbsp; System.Console.WriteLine(t.ToString());&lt;BR&gt;}&lt;BR&gt;static void PrintTree&amp;lt;T&amp;gt;(Tree&amp;lt;T&amp;gt; t){&lt;BR&gt;&amp;nbsp; Traverse(t, DepthFirstTraversal, Print);&lt;BR&gt;}&lt;BR&gt;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;What if we wanted that last one to use lambdas? &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;static void PrintTree&amp;lt;T&amp;gt;(Tree&amp;lt;T&amp;gt; t){&lt;BR&gt;&amp;nbsp; Traversal&amp;lt;T&amp;gt; df = (t, a)=&amp;gt;{&lt;BR&gt;&amp;nbsp; &amp;nbsp; if(t==null) return;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; a(t.Value);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; df(t.Left, a);&lt;BR&gt;&amp;nbsp; &amp;nbsp; df(t.Right, a);&lt;BR&gt;&amp;nbsp; };&lt;BR&gt;&amp;nbsp; Traverse(t, df, Print);&lt;BR&gt;}&lt;BR&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;That doesn't work because it's a definite assignment error. The compiler says that local variable df is being used before it is assigned. You'd have to say &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;Traversal&amp;lt;T&amp;gt; df = null;&lt;BR&gt;df = (t, a)=&amp;gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;And suddenly it would start working. &lt;/P&gt;
&lt;P&gt;What the heck? I mean, the original code is a syntactic sugar for: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;privateclass Locals{&lt;BR&gt;&amp;nbsp; public Traversal&amp;lt;T&amp;gt; df; &lt;BR&gt;&amp;nbsp; public void M&amp;lt;T&amp;gt;(Tree&amp;lt;T&amp;gt; t, Action&amp;lt;T&amp;gt; a){ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(t==null) return;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; a(t.Value);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.df(t.Left, a);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.df(t.Right, a);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN class=code&gt;&lt;SPAN class=code&gt;static void PrintTree&amp;lt;T&amp;gt;(Tree&amp;lt;T&amp;gt; t){&lt;BR&gt;&lt;/SPAN&gt;&amp;nbsp; Locals locals = new Locals();&lt;BR&gt;&amp;nbsp; locals.df = new Traversal&amp;lt;T&amp;gt;(locals.M&amp;lt;T&amp;gt;);&lt;BR&gt;&amp;nbsp; Traverse(t, locals.df, Print);&lt;BR&gt;}&lt;BR&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;And clearly there is no use-before-initialization problem there. &lt;/P&gt;
&lt;P&gt;The reason this is an error is because though there is actually no definite assignment problem here, it is not too hard to find a similar situation which does create a problem. Here's a silly example that nevertheless demonstrates a real problem: &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;delegate D D(D d); &lt;BR&gt;//... &lt;BR&gt;D d = ((D)(c=&amp;gt;c(d))(e=&amp;gt;e); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;If you trace out the logic of that thing you'll find that in fact the local variable delegate d is potentially used before it is initialized, and therefore this must be an error. &lt;/P&gt;
&lt;P&gt;We could immensely complicate the definite assignment rules by adding rules to discover which lambda and anonymous method bodies are guaranteed to be never called during the initialization, and therefore suppress definite assignment errors on some locals in their bodies. But one of the goals of the standardization process is to make rules that are clear and unambiguous and comprehensible by mortals; enabling recursive anonymous methods isn't a big enough win for the amount of complexity, particularly when you consider that there is the simple workaround of assigning to null and then reassigning. &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=706398" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Lambda+Expressions/default.aspx">Lambda Expressions</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category></item><item><title>Recursion, Part Six: Making CPS Work</title><link>http://blogs.msdn.com/ericlippert/archive/2005/08/15/recursion-part-six-making-cps-work.aspx</link><pubDate>Mon, 15 Aug 2005 13:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:442714</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/442714.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=442714</wfw:commentRss><description>&lt;FONT face="lucida sans unicode" color=purple size=2&gt;
&lt;P&gt;JScript doesn't support CPS natively but we can write another dispatch engine that makes it work. There's only ever one active continuation, so lets have a new rule:&amp;nbsp; JScript CPS&amp;nbsp;functions are allowed to return, but the last thing that they do must be to tell our dispatch engine what the continuation was.&lt;/P&gt;
&lt;P&gt;To keep things simple, we'll also say &lt;STRONG&gt;that every CPS-style function takes exactly one argument&lt;/STRONG&gt;. Of course, that can be an object that contains multiple fields should the function require multiple arguments.&lt;/P&gt;
&lt;P&gt;Let's go through our CPS treeDepth program and replace all the continuation calls with calls that tell the runtime engine what continuation to use next.&amp;nbsp; We'll then return normally and let the runtime engine call the continuation for us.&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function treeDepth(args)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; if (args.curtree == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cont(args.afterDepth, 0);&lt;BR&gt;&amp;nbsp; else&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function afterLeft(leftDepth)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function afterRight(rightDepth)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cont(args.afterDepth, 1+Math.max(leftDepth, rightDepth));&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cont(treeDepth, {curtree: args.curtree.right, afterDepth: afterRight});&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cont(treeDepth, {curtree: args.curtree.left, afterDepth: afterLeft});&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;The dispatch engine is very simple:&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;var continuation = null;&lt;BR&gt;function cont(newfunc, newargs)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; continuation = { func: newfunc, args : newargs };&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;function run()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; while(continuation != null)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var curfunc = continuation.func;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var curargs = continuation.args;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; continuation = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; curfunc(curargs);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;No stack at all this time. Just a single global variable saying what to call next. If there is nothing to call next, we're done. To determine the depth of a tree we simply tell the continuation engine what the next thing to do is, and start it running:&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;cont(treeDepth, {curtree: mytree, afterDepth: print});&lt;BR&gt;run();&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;and hey presto, we've just implemented a recursive function with no stack that prints the depth of an arbitrary binary tree.&lt;/P&gt;
&lt;P&gt;Nice trick! Of course, &lt;STRONG&gt;really what we've done is we've just hidden the call stack in another harder-to-see data structure. Where is it?&lt;/STRONG&gt; (Hint: draw some diagrams that show what all the closure name table bindings are during the recursion.)&lt;/P&gt;
&lt;P&gt;That's all I managed to get done here before my vacation. When I get back, maybe I'll &lt;EM&gt;pop the stack&lt;/EM&gt; and pick up where we left off, or maybe I'll &lt;EM&gt;continue&lt;/EM&gt; with something completely different and forget all about my current state.&amp;nbsp; (Or maybe I'm actually interrupt driven, which seems most likely.) Who knows? Whatever happens though, it'll probably be another &lt;STRONG&gt;fabulous adventure in coding&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;***********************************&lt;/P&gt;
&lt;P&gt;Further reading:&lt;/P&gt;
&lt;P&gt;Don Box on closures and CPS in C# 2.0: &lt;A href="http://pluralsight.com/blogs/dbox/archive/2005/04/27/7780.aspx"&gt;http://pluralsight.com/blogs/dbox/archive/2005/04/27/7780.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;(Eric is on vacation; this message was pre-recorded.)&amp;nbsp;&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=442714" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Rarefied+Heights/default.aspx">Rarefied Heights</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Continuation+Passing+Style/default.aspx">Continuation Passing Style</category></item><item><title>Recursion, Part Five: More on CPS</title><link>http://blogs.msdn.com/ericlippert/archive/2005/08/11/recursion-part-five-more-on-cps.aspx</link><pubDate>Thu, 11 Aug 2005 13:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:442711</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/442711.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=442711</wfw:commentRss><description>&lt;FONT face="lucida sans unicode" color=purple size=2&gt;
&lt;P&gt;Suppose we wanted to write this by-now-familiar little function in continuation passing style:&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function treeDepth(curtree)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; if (curtree == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 0;&lt;BR&gt;&amp;nbsp; else&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var leftDepth = treeDepth(curtree.left);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var rightDepth = treeDepth(curtree.right);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 1 + Math.max(leftDepth, rightDepth);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;Let's start by getting rid of the returns, since there are no returns in CPS. Rather, we "return" by passing the return value to the continuation. Remember, the continuation is "what are we supposed to do after this function is done?"&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function treeDepth(curtree, afterDepth)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; if (curtree == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; afterDepth(0);&lt;BR&gt;&amp;nbsp; else&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //UNDONE: var leftDepth = treeDepth(curtree.left);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //UNDONE: var rightDepth = treeDepth(curtree.right);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; afterDepth(1 + Math.max(leftDepth, rightDepth));&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;We'll presume that the addition and maximum&amp;nbsp;guys are not written in CPS, just to keep this simple.&lt;/P&gt;
&lt;P&gt;OK, this is a start, but now we need to fix up those recursive calls.&amp;nbsp; Consider the second recursive call.&amp;nbsp; What is its continuation?&amp;nbsp; That is, what needs to happen after the right tree depth is determined?&amp;nbsp; Two things. First, the maximum of left and right must be calculated and incremented.&amp;nbsp; Second, we've promised our caller that when we're done, we'll call its continuation.&amp;nbsp; So let's write a closure that does those two things.&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function treeDepth(curtree, afterDepth)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; if (curtree == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; afterDepth(0);&lt;BR&gt;&amp;nbsp; else&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function afterRight(rightDepth)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; afterDepth(1 + Math.max(leftDepth, rightDepth));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // UNDONE: var leftDepth = treeDepth(curtree.left);&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; treeDepth(curtree.right, afterRight);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;We're making progress. What do we need to do after we determine the depth of the left tree?&amp;nbsp; Pass the left depth to a continuation that recurses on the right tree to determine the right depth,&amp;nbsp;does the max, and calls the &lt;FONT color=#000080&gt;afterDepth&lt;/FONT&gt; continuation.&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function treeDepth(curtree, afterDepth)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; if (curtree == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; afterDepth(0);&lt;BR&gt;&amp;nbsp; else&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function afterLeft(leftDepth)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function afterRight(rightDepth)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; afterDepth(1 + Math.max(leftDepth, rightDepth));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; treeDepth(curtree.right, afterRight);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; treeDepth(curtree.left, afterLeft);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;And we're done.&amp;nbsp; We've got a CPS version of &lt;FONT color=#000080&gt;treeDepth&lt;/FONT&gt; which never returns and therefore we never need to keep track of what is on the stack, because we're never coming back.&lt;/P&gt;
&lt;P&gt;Of course, like I said last time, in reality JScript does &lt;STRONG&gt;not&lt;/STRONG&gt; detect that we're in this situation and optimize away the stack frames.&amp;nbsp; This program still pushes interpreters on the system stack and still runs out of stack space if you have a 1500-deep branch in your tree.&lt;/P&gt;
&lt;P&gt;But we can fake it out.&amp;nbsp; Next time, we'll finish up with a CPS program that really doesn't run out of stack space, even in JScript.&lt;/P&gt;
&lt;P&gt;(Eric is on vacation; this message was pre-recorded.)&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=442711" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Rarefied+Heights/default.aspx">Rarefied Heights</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Continuation+Passing+Style/default.aspx">Continuation Passing Style</category></item><item><title>Recursion, Part Four: Continuation Passing Style</title><link>http://blogs.msdn.com/ericlippert/archive/2005/08/08/recursion-part-four-continuation-passing-style.aspx</link><pubDate>Mon, 08 Aug 2005 13:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:442706</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/442706.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=442706</wfw:commentRss><description>&lt;FONT face="lucida sans unicode" color=purple size=2&gt;
&lt;P&gt;We're getting hung up on the stack management aspects of recursive programming. &lt;STRONG&gt;Why do we need a stack at all? What purpose does it serve?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;If you're like most developers, you probably learned about subroutines and functions at an early age. The idea is pretty straightforward.&amp;nbsp; You stop what you're doing right now, go perform some other task, and then pick up where you left off, possibly using data computed by the other task.&amp;nbsp; But this idea of "pick up where you left off" means that you have to have some mechanism for storing information about what you were doing and where to pick it up. A stack is a natural data structure for that, so we've been thinking a lot about stacks lately when we consider how to operate on recursive data structures.&lt;/P&gt;
&lt;P&gt;But what if we simply denied the whole premise of functions? What if we said that &lt;STRONG&gt;no function was ever allowed to return&lt;/STRONG&gt;?&amp;nbsp; It either terminates the program, or itself calls another function.&lt;/P&gt;
&lt;P&gt;You might be thinking that clearly the cure is worse than the disease.&amp;nbsp; I mean, sure, now you don't have to keep track of what you were doing, but that's because you're never going to get back there!&amp;nbsp; How is it possible to get any work done at all if every time you try to call a procedure for a little help, it takes over control and never comes back to you?&lt;/P&gt;
&lt;P&gt;This sounds like crazy talk, but let's think about the consequences of removing all returns from the language. Three things are clear. &lt;/P&gt;
&lt;P&gt;First, if you yourself write a function then &lt;STRONG&gt;calling another function has to be the last thing you do&lt;/STRONG&gt;. Control is never coming back, so there's no point in having any code after a function call. &lt;/P&gt;
&lt;P&gt;Second, suppose you have more work to do after you call a function foo. Foo is in the same position as you -- the last thing it does will either be a function call or terminating the program. Therefore, you need to put the work that needs to be done after foo into function bar, and make for darn sure that foo calls bar rather than terminating!&lt;/P&gt;
&lt;P&gt;But if you didn't write foo, how do you know that foo is going to call bar when its done?&amp;nbsp; You need to somehow tell foo to call bar, and hope that foo cooperates.&lt;/P&gt;
&lt;P&gt;Third, if someone calls your function then&amp;nbsp;they're in the same boat -- it's the last thing they're going to do, ever, because you're not coming back. You need to find some way to allow your caller to tell you what to do when you're done your work. &lt;/P&gt;
&lt;P&gt;This idea of functions never returning, and callers passing their functions information about what needs to be done next, is a bizarre but powerful style of programming called &lt;STRONG&gt;Continuation Passing Style&lt;/STRONG&gt;. The "information about what to do next" is called a "continuation", which is passed from function to function, hence the name.&lt;/P&gt;
&lt;P&gt;Many languages support CPS natively -- Scheme, Ruby and Rhino, for example, all support CPS.&amp;nbsp; To get it working in JScript will take some doing, but when we're done there will be no explicit stack at all in our formerly recursive program.&lt;/P&gt;
&lt;P&gt;In the next episode I'm going to write our tree depth program in a mix of CPS and regular procedural programming. (To be purely CPS we'd write CPS versions of the addition operators, the &lt;FONT style="BACKGROUND-COLOR: #ffffff" color=#000080&gt;Math.max&lt;/FONT&gt; function, and so on, but I'm not going to go there&amp;nbsp; -- that's overkill.)&amp;nbsp; But before we get into the tree depth program let's get a little more familiar with CPS.&lt;/P&gt;
&lt;P&gt;Suppose we had this fragment of a JScript program:&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function foo(x)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; var y = bar();&lt;BR&gt;&amp;nbsp; blah(x,y); &lt;BR&gt;}&lt;BR&gt;function bar()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; return 123;&lt;BR&gt;}&lt;BR&gt;function blah(a, b)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; print(a+b);&lt;BR&gt;}&lt;BR&gt;foo(1);&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;I hope you agree that this is a very straightforward program. How would we do this in CPS?&amp;nbsp; Well, first of all, every function would have to take an extra argument for the continuation. Our program calls foo and then terminates, so the continuation of the call to foo is "terminate the program".&amp;nbsp; Let's presume that we have a magic function that does that.&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function foo(x, cfoo)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; // UNDONE: rewrite foo in CPS&lt;BR&gt;}&lt;BR&gt;foo(1, terminate);&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;Let's reason about &lt;FONT color=#000080&gt;foo&lt;/FONT&gt; from end to start. &lt;FONT color=#000080&gt;foo&lt;/FONT&gt; wants to ensure that three things happen in this order: &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT color=#000080&gt;bar&lt;/FONT&gt; runs 
&lt;LI&gt;&lt;FONT color=#000080&gt;blah&lt;/FONT&gt; runs 
&lt;LI&gt;&lt;FONT color=#000080&gt;foo&lt;/FONT&gt;'s continuation from its caller runs&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;But &lt;FONT color=#000080&gt;blah&lt;/FONT&gt; is never going to return.&amp;nbsp;&lt;STRONG&gt; Therefore we'll make it &lt;FONT color=#000080&gt;blah&lt;/FONT&gt;'s responsibility to call &lt;FONT color=#000080&gt;foo&lt;/FONT&gt;'s continuation when it is done.&lt;/STRONG&gt; We'll rewrite &lt;FONT color=#000080&gt;blah&lt;/FONT&gt; so that it does CPS, so that we can say:&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function foo(x, cfoo)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; var y = bar();&lt;BR&gt;&amp;nbsp; blah(x,y,cfoo); &lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;OK, super, we've taken care of our responsibility to our caller by foisting it off onto &lt;FONT color=#000080&gt;blah&lt;/FONT&gt;.&amp;nbsp; But now we have an additional problem. &lt;FONT color=#000080&gt;bar&lt;/FONT&gt; is never going to return, so we're never going to call &lt;FONT color=#000080&gt;blah&lt;/FONT&gt;!&amp;nbsp; We've both failed in our responsibility to our caller and haven't done the work we need to do.&lt;/P&gt;
&lt;P&gt;We have an additional problem. &lt;FONT color=#000080&gt;bar&lt;/FONT&gt; was going to return a value that we were going to use. But we've just removed returns from the language! Let's solve both of these problems.&amp;nbsp; We'll&amp;nbsp;say that &lt;FONT color=#000080&gt;bar&lt;/FONT&gt; takes a continuation and &lt;STRONG&gt;passes the value that it was going to return as an argument to its continuation&lt;/STRONG&gt;. That's functionally the same thing, right? Before, you return the value to "whatever you were going to do next", now you pass the value to "whatever you were going to do next", same thing.&lt;/P&gt;
&lt;P&gt;But what continuation should &lt;FONT color=#000080&gt;foo&lt;/FONT&gt; pass to &lt;FONT color=#000080&gt;bar&lt;/FONT&gt;?&amp;nbsp; Well, what does &lt;FONT color=#000080&gt;foo&lt;/FONT&gt; want done when &lt;FONT color=#000080&gt;bar&lt;/FONT&gt; calls its continuation with its "return" value?&amp;nbsp; That's easy. It wants to call &lt;FONT color=#000080&gt;blah&lt;/FONT&gt; with that value and &lt;FONT color=#000080&gt;foo&lt;/FONT&gt;'s original arguments.&amp;nbsp;We can&amp;nbsp;write a helper function that does that.&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function foo(x, afterfoo)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; function foocontinuation(y)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; blah(x,y,afterfoo); &lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; bar(foocontinuation);&lt;BR&gt;}&lt;BR&gt;function bar(afterbar)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; afterbar(123);&lt;BR&gt;}&lt;BR&gt;function blah(a, b, afterblah)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; print(a+b, afterblah); // print also rewritten in CPS&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;foo(1, terminate);&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#000080&gt;foocontinuation&lt;/FONT&gt; is a &lt;a href="http://blogs.msdn.com/ericlippert/archive/2003/09/17/53028.aspx"&gt;closure&lt;/A&gt;, so it keeps track of what the values of &lt;FONT color=#000080&gt;x&lt;/FONT&gt; and &lt;FONT color=#000080&gt;afterfoo&lt;/FONT&gt; were when it was passed to &lt;FONT color=#000080&gt;bar&lt;/FONT&gt;.&amp;nbsp; So we're all set here.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The global code passes 1, &lt;FONT color=#000080&gt;terminate&lt;/FONT&gt; to &lt;FONT color=#000080&gt;foo&lt;/FONT&gt;&amp;nbsp; &lt;BR&gt;&lt;FONT color=#000080&gt;foo&lt;/FONT&gt; passes &lt;FONT color=#000080&gt;foocontinuation&lt;/FONT&gt; to &lt;FONT color=#000080&gt;bar&lt;/FONT&gt;&lt;BR&gt;&lt;FONT color=#000080&gt;bar&lt;/FONT&gt; passes 123 to &lt;FONT color=#000080&gt;foocontinuation&lt;/FONT&gt;&amp;nbsp; &lt;BR&gt;&lt;FONT color=#000080&gt;foocontinuation&lt;/FONT&gt; passes 1, 123, &lt;FONT color=#000080&gt;terminate&lt;/FONT&gt; to &lt;FONT color=#000080&gt;blah&lt;/FONT&gt;&lt;BR&gt;&lt;FONT color=#000080&gt;blah&lt;/FONT&gt; adds together its arguments and passes 124, &lt;FONT color=#000080&gt;terminate&lt;/FONT&gt; to &lt;FONT color=#000080&gt;print&lt;/FONT&gt;&lt;BR&gt;&lt;FONT color=#000080&gt;print&lt;/FONT&gt; presumably prints out 124 and calls &lt;FONT color=#000080&gt;terminate&lt;/FONT&gt;, and we're done&lt;/P&gt;
&lt;P&gt;Not once did any function return in there, and we did everything in the right order.&lt;/P&gt;
&lt;P&gt;Now of course in reality, JScript does not know that none of these functions are going to return. Nor is JScript smart enough to realize that even if they did return, none of these functions now does anything after the subroutine call, and therefore keeping track of the old frames on the stack is unnecessary, since they're never going to be read from again. If it did, we could totally write programs in this style and never worry about running out of stack space, but unfortunately, it doesn't.&lt;/P&gt;
&lt;P&gt;But just as we helped JScript along by writing our own explicit frame stack, we can help it along by writing our own CPS system. Stay tuned!&lt;/P&gt;
&lt;P&gt;(Eric is on vacation; this message was prerecorded.)&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=442706" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Rarefied+Heights/default.aspx">Rarefied Heights</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Continuation+Passing+Style/default.aspx">Continuation Passing Style</category></item><item><title>Recursion, Part Three: Building a Dispatch Engine</title><link>http://blogs.msdn.com/ericlippert/archive/2005/08/04/recursion-part-three-building-a-dispatch-engine.aspx</link><pubDate>Thu, 04 Aug 2005 13:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:442691</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/442691.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=442691</wfw:commentRss><description>&lt;FONT face="lucida sans unicode" color=purple size=2&gt;
&lt;P&gt;There's a particular technique that I like to use to solve problems -- it doesn't always work, but when it does, it can produce programs of surprising elegance and power. The technique is this: if you have a specific problem to solve, solve a more general problem, and then your problem is just a special case. It's like that joke someone mentioned during my series on high-dimensional arithmetic -- it's easy to imagine a 9-dimensional space, just imagine an n-dimensional space and set n=9.&lt;/P&gt;
&lt;P&gt;That sounds like more work, doesn't it?&amp;nbsp; Often it is, but paradoxically, sometimes it's less work.&lt;/P&gt;
&lt;P&gt;Our solution last time for de-recursivizing a three-line recursive algorithm was an unreadable mess in part because the explicit stack logic was all mixed up with the bits of the function actually doing work. Rather than messing around trying to implement JScript's call logic in JScript itself, complete with frames and return values and activation objects, let's solve a more general problem. Let's build a little dispatch engine, and build some functions that use that dispatch engine to solve problems. Solving tree depth will then just be a special case.&lt;/P&gt;
&lt;P&gt;Our dispatch engine will have two stacks: the functions-I-still-need-to-call stack, and the values-to-pass-to-them stack.&amp;nbsp; But to keep it simple, the functions themselves will be responsible for taking the values on and off the value stack. With those design characteristics, our "dispatch engine" becomes very, very simple.&amp;nbsp; It just pops a function off the function stack and calls it. When there are no more functions on the stack, we're done.&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;while(functionstack.length != 0)&lt;BR&gt;&amp;nbsp; functionstack.pop()();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;We'll need to do a little stack magic to make it all work, but we can do it. We'll call the functions D, R and M:&lt;/P&gt;
&lt;P&gt;D:&lt;BR&gt;&lt;STRONG&gt;action&lt;/STRONG&gt;: either computes the depth of a null&amp;nbsp;node or pushes a program that "recursively" computes the depth of a node.&lt;BR&gt;&lt;STRONG&gt;value stack precondition&lt;/STRONG&gt;: value stack top contains tree node&lt;BR&gt;&lt;STRONG&gt;value stack postcondition&lt;/STRONG&gt;: if tree node on stack is null, replace it with zero. Otherwise push right and left trees&lt;BR&gt;&lt;STRONG&gt;function stack postcondition&lt;/STRONG&gt;: if tree node is not null, push MDRD onto function stack&lt;/P&gt;
&lt;P&gt;R: &lt;BR&gt;&lt;STRONG&gt;action&lt;/STRONG&gt;: reorganizes the value stack so that the depth of the right tree can be determined&lt;BR&gt;&lt;STRONG&gt;value stack precondition&lt;/STRONG&gt;: top of stack is left tree depth, followed by tree node&lt;BR&gt;&lt;STRONG&gt;value stack postcondition&lt;/STRONG&gt;: top of stack is tree node, followed by left tree depth&lt;BR&gt;&lt;BR&gt;M:&lt;BR&gt;&lt;STRONG&gt;action&lt;/STRONG&gt;: takes the max + 1 of two numbers&lt;BR&gt;&lt;STRONG&gt;value stack precondition&lt;/STRONG&gt;: two numbers on top of stack&lt;BR&gt;&lt;STRONG&gt;value stack postcondition&lt;/STRONG&gt;: one number on top of stack&lt;/P&gt;
&lt;P&gt;Does that make sense?&amp;nbsp; Let's think about how that would play out for a tree with root B, left child A, right child C.&amp;nbsp; I'll use X to represent an empty (null) tree. We put D on the function stack and B on the value stack and start the engine:&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;functions values&amp;nbsp;notes&lt;BR&gt;D&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; B&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;B is not null, so we push its children on the value stack and MDRD on the function stack&lt;BR&gt;MDRD&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CA&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Again, D is the top of the function stack, so we do it again, this time on A&lt;BR&gt;MDRMDRD&amp;nbsp;&amp;nbsp; CXX&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Now D is at the top of the function stack and we have a null. Replace it with zero.&lt;BR&gt;MDRMDR &amp;nbsp;&amp;nbsp; CX0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Swap the top two &lt;BR&gt;MDRMD&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C0X&amp;nbsp;&amp;nbsp;&amp;nbsp; Replace null with zero&lt;BR&gt;MDRM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C00&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;M pops both numbers, finds the larger, adds one, pushes it&lt;BR&gt;MDR&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Swap the top two, replace the tree with its right child&lt;BR&gt;MD&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1C&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;and so on...&lt;BR&gt;MMDRD&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1XX&lt;BR&gt;MMDR&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1X0&lt;BR&gt;MMD&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10X&lt;BR&gt;MM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 100&lt;BR&gt;M&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;And if we've done it right, when we're done the value stack contains the depth of the tree that we started with, and the function stack is empty.&lt;/P&gt;
&lt;P&gt;Looks promising. Let's write the code.&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;var functionstack = new Array();&lt;BR&gt;var valuestack = new Array();&lt;/P&gt;
&lt;P&gt;function treeDepth()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; var curtree = valuestack.pop();&lt;BR&gt;&amp;nbsp; if (curtree == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; valuestack.push(0);&lt;BR&gt;&amp;nbsp; else&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; functionstack.push(max);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; functionstack.push(treeDepth);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; functionstack.push(reorder);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; functionstack.push(treeDepth);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; valuestack.push(curtree.right);&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; valuestack.push(curtree.left);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;function reorder()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; var leftdepth = valuestack.pop();&lt;BR&gt;&amp;nbsp; var righttree = valuestack.pop();&lt;BR&gt;&amp;nbsp; valuestack.push(leftdepth);&lt;BR&gt;&amp;nbsp; valuestack.push(righttree);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;function max()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; valuestack.push(1 + Math.max(valuestack.pop(), valuestack.pop()));&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;functionstack.push(treeDepth);&lt;BR&gt;valuestack.push(mytree);&lt;BR&gt;while(functionstack.length != 0)&lt;BR&gt;&amp;nbsp; functionstack.pop()();&lt;BR&gt;print(valuestack.pop());&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;Each function is a lot cleaner now that the execution management has been pushed to an external engine. But we've paid a pretty high price in that it's now non-obvious that this program &lt;EM&gt;actually works&lt;/EM&gt; on all trees. I mean, it sure looks like it works, but we haven't proven it. But at least its not directly recursive, so we're pretty sure that we don't have to worry about running out of system stack.&lt;/P&gt;
&lt;P&gt;This time we attacked the problem of eliminating recursion by getting rid of the notion of explicit frames on the stack. Next time we'll take a very different tack and try to eliminate stacks altogether.&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;(Eric is on vacation; this message was pre-recorded.)&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=442691" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Rarefied+Heights/default.aspx">Rarefied Heights</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category></item><item><title>Recursion, Part Two: Unrolling a Recursive Function With an Explicit Stack</title><link>http://blogs.msdn.com/ericlippert/archive/2005/08/01/recursion-part-two-unrolling-a-recursive-function-with-an-explicit-stack.aspx</link><pubDate>Mon, 01 Aug 2005 13:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:442606</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/442606.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=442606</wfw:commentRss><description>&lt;FONT face="lucida sans unicode" color=purple size=2&gt;
&lt;P&gt;That recursive solution is pretty cool, to be sure.&amp;nbsp;But there&amp;nbsp;is one big problem&amp;nbsp;with it.&amp;nbsp; Consider this Jscript program that puts a few more nodes into our tree from last time:&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function tree(value, left, right)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; this.value = value;&lt;BR&gt;&amp;nbsp;&amp;nbsp;this.left = left;&lt;BR&gt;&amp;nbsp;&amp;nbsp;this.right = right;&lt;BR&gt;}&lt;BR&gt;for (var i = 1 ; i &amp;lt; 1500 ; ++i)&lt;BR&gt;&amp;nbsp;&amp;nbsp;mytree = new tree(i, mytree, null)&lt;BR&gt;print(treeDepth(mytree));&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;This is not a very well-behaved binary tree – it’s actually mostly a linked list, hardly a tree at all.&amp;nbsp; Recursing down 1500 branches to get to the bottom blows the stack.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Each time you enter a JScript function, that pushes a new JScript "activation" frame on the JScript stack. But the JScript stack is actually allocated off of the system heap, so this isn't&amp;nbsp;the problem. Unfortunately,&amp;nbsp;doing so&amp;nbsp;also pushes a new copy of the interpreter on the &lt;STRONG&gt;system&lt;/STRONG&gt; stack, which consumes a few hundred bytes of stack space.&amp;nbsp; Since by default the system stack only has a million bytes available, this quickly consumes the entire system stack. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Recursive functions are sometimes the most elegant solution, but not always the most practical.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;How are we going to solve this problem?&lt;/P&gt;
&lt;P&gt;One way to do it is to not get into the situation in the first place. There are various algorithms for guarateeing that when you construct a binary tree that it is a "balanced" binary tree. That is, there are no long, deep paths. A &lt;EM&gt;perfectly&lt;/EM&gt; balanced binary tree with 1500 nodes in it is guaranteed to require no more than 11 recursive steps, and doubling the number of nodes only adds on one more step.&amp;nbsp; A perfect&amp;nbsp;tree with a million nodes requires no more than 20 recursive steps, so odds are pretty good that you'll never blow the stack if you know you have a balanced tree.&amp;nbsp; There are algorithms such as the famous red-black algorithm that guarantee that a binary tree is always within a factor of two of being perfectly balanced, so maybe a million-node tree is 40 deep, which seems doable.&lt;/P&gt;
&lt;P&gt;Another approach is to keep track of how deep you are on the stack and bail out:&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function treeDepth(curtree, stackdepth)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; if (curtree == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 0;&lt;BR&gt;&amp;nbsp; if (stackdepth &amp;gt; 1000)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw&amp;nbsp;"tree is&amp;nbsp;too deep, bailing out!";&lt;BR&gt;&amp;nbsp; return 1 + Math.max(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; treeDepth(curtree.left, stackdepth + 1), &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; treeDepth(curtree.right, stackdepth + 1));&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;But that's pretty hacked up. What if you're wrong about how much stack you have left?&amp;nbsp;Maybe 1000 is too deep. What if you can't guarantee that the tree is balanced?&amp;nbsp; What if you want to have an algorithm that works for &lt;EM&gt;any&lt;/EM&gt; binary tree without danger of blowing the stack or getting a goofy exception?&lt;/P&gt;
&lt;P&gt;Some languages, such as Scheme, have what’s called “tail recursion”, where they detect when they can optimize away pushing another frame on the stack, and therefore do not have this problem. But JScript does not have this optimization, and even if it did, this tree algorithm is a poor candidate for tail recursion. Tail recursion works really well when the recursive step is last, but this algorithm has &lt;EM&gt;two&lt;/EM&gt; recursive steps, so one of them is going to be not last, obviously. (Though as we'll see in a few episodes, there are things we can do about that.)&lt;/P&gt;
&lt;P&gt;Hmm. &lt;/P&gt;
&lt;P&gt;I just said that the JScript stack is actually allocated off of the system heap -- the interpreter simulates a stack for the script engines rather than re-using the system stack. We can do the same thing with our recursive program: &lt;STRONG&gt;make the stack explicit rather than implicit.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;That's going to be complicated. Think about what has to happen every time you call a function in JScript. Somehow the interpreter has to remember a whole bunch of things, like:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;values of local variables in the current activation frame -- variables and arguments in the callee's frame&amp;nbsp;must not change the variables in the caller's frame. 
&lt;LI&gt;where to pick up execution when the callee returns 
&lt;LI&gt;what to do with the return value of the callee 
&lt;LI&gt;values of "anonymous locals" -- for example, when you have &lt;FONT color=#000080&gt;x = 1 + 1 + foo(); &lt;/FONT&gt;somehow the engine has to remember that there's a 2 sitting there in temporary storage waiting to be added when foo returns.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Let's take our recursive depth algorithm and refactor it a little bit so that the temporary variables are spelled out and each recursion happens on its own line:&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function treeDepth(curtree)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; if (curtree == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 0;&lt;BR&gt;&amp;nbsp; var leftdepth = treeDepth(curtree.left);&lt;BR&gt;&amp;nbsp; var rightdepth = treeDepth(curtree.right);&lt;BR&gt;&amp;nbsp; return 1 + Math.max(leftdepth, rightdepth);&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;For each recursive step we'll need a frame that keeps track of what the three local variables are.&amp;nbsp; Before each recursion we need to remember where we were, so that when we start executing, we know whether to pick up on the "&lt;FONT color=#000080&gt;var leftdepth&lt;/FONT&gt;..." line or "&lt;FONT color=#000080&gt;var rightdepth&lt;/FONT&gt;..." line or the "&lt;FONT color=#000080&gt;return 1 +&lt;/FONT&gt; ..." line.&amp;nbsp; We'll remember that by keeping track of whether &lt;FONT color=#000080&gt;leftdepth&lt;/FONT&gt; and/or &lt;FONT color=#000080&gt;rightdepth&lt;/FONT&gt; are initialized on the frame.&amp;nbsp; When we complete a calculation we'll pop off the current frame and fill in the "calling" frame's variables with the appropriate "return value" so that our execution loop knows where to go next.&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function treeDepth(curtree)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; if (curtree == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 0;&lt;BR&gt;&amp;nbsp; var frame = { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; curtree:&amp;nbsp;&amp;nbsp;&amp;nbsp; curtree, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; leftdepth:&amp;nbsp; null, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rightdepth: null};&lt;BR&gt;&amp;nbsp; var stack = new Array();&lt;BR&gt;&amp;nbsp; stack.push(frame);&lt;BR&gt;&amp;nbsp; while(true)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var curframe = stack[stack.length-1];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (curframe.curtree == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stack.pop();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; curframe = stack[stack.length-1];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (curframe.leftdepth == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; curframe.leftdepth = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; curframe.rightdepth = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (curframe.leftdepth == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; curframe = {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; curtree:&amp;nbsp;&amp;nbsp; &amp;nbsp;curframe.curtree.left, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; leftdepth: &amp;nbsp;null, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;rightdepth: null};&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stack.push(curframe);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (curframe.rightdepth == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; curframe = {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; curtree:&amp;nbsp;&amp;nbsp;&amp;nbsp; curframe.curtree.right, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; leftdepth:&amp;nbsp; null, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rightdepth: null};&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stack.push(curframe);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var depth = 1 + Math.max(curframe.leftdepth, curframe.rightdepth);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stack.pop();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (stack.length == 0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return depth;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; curframe = stack[stack.length-1];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (curframe.leftdepth == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; curframe.leftdepth = depth;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; curframe.rightdepth = depth;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;Since there is no recursion here at all now, there's no danger of running out of stack. But good heavens, that's &lt;STRONG&gt;a freakin' mess compared to the three-line recursive solution. &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;This is probably more trouble than it's worth. Next time we'll look at another explicit-stack based approach that is a whole lot cleaner than this dog's breakfast.&lt;/P&gt;
&lt;P&gt;(Eric is on vacation; this message was prerecorded.)&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=442606" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Rarefied+Heights/default.aspx">Rarefied Heights</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category></item><item><title>Recursion, Part One: Recursive Data Structures and Functions</title><link>http://blogs.msdn.com/ericlippert/archive/2005/07/27/recursion-part-one-recursive-data-structures-and-functions.aspx</link><pubDate>Wed, 27 Jul 2005 13:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:442590</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/442590.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=442590</wfw:commentRss><description>&lt;FONT face="lucida sans unicode" color=purple size=2&gt;
&lt;P&gt;The first thing to wrap your head around is recursively defined data structures. Let's start with something simple.&amp;nbsp; Think about the abstract idea of “list”.&amp;nbsp; Most people think of a “list” as an ordered collection of “items”, one after the other, with a beginning and an end.&amp;nbsp; That’s a very non-recursive way to think about a list, but it’s the usual way of doing so.&lt;/P&gt;
&lt;P&gt;The recursive way to think about a list emphasizes the similarity of a fragment of the list to the whole list.&amp;nbsp; We might recursively define a list as either&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;the empty list with zero items on it, or 
&lt;LI&gt;an item followed by a list.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;This certainly appears to be a circular definition, but it’s really not.&amp;nbsp;It’s more sort of a “spiral” definition. You start off with something extremely simple; it’s harder to get more simple than a list with no elements. Then you provide a rule for turning something simple into something &lt;EM&gt;very slightly&lt;/EM&gt; more complicated.&amp;nbsp;The recursive part of the definition means that you can take a list of any size, starting with zero, and construct a list one bigger than it, by sticking an item on to the beginning. It’s not a truly circular definition because there is always a “base case”.&amp;nbsp;There is always some point from which you begin, and upon which you can build. &lt;/P&gt;
&lt;P&gt;But the true power of the recursive definition comes from going the other way: if you have something that meets the definition, then there is usually a way to move back towards the base case, getting simpler and simpler as you go.&lt;/P&gt;
&lt;P&gt;That’s what recursive programming is all about.&amp;nbsp;All recursive functions follow the same basic pattern:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Am I in the base case? If so, return the easy solution. 
&lt;LI&gt;Otherwise, figure out some way to make the problem closer to the base case and solve that problem. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;That’s why you can get away with calling a function from itself – because you know that the recursion will eventually bottom out when you’ve found the base case. &lt;/P&gt;
&lt;P&gt;Now, for list processing, a recursive solution is usually overkill. The iterative solution of “run down the list in a loop” is usually good enough. But many other problems are naturally solved by other recursively defined data structures.&amp;nbsp;For example, consider the highly useful binary tree.&amp;nbsp;A binary tree is either:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;an empty tree, or 
&lt;LI&gt;a value associated with two binary search trees, called the left and right child trees &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;For example, this is a binary tree:&lt;/P&gt;&lt;FONT face="lucida console"&gt;
&lt;P&gt;&lt;FONT color=#000080&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; E&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; / \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /&amp;nbsp;&amp;nbsp; \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; B&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; G&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; / \&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; A&amp;nbsp;&amp;nbsp; C&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; H&lt;/FONT&gt;&amp;nbsp; &lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;The children of A, C and H, and the left child of G, are empty trees. (Sharp eyed readers will have noted that this particular example is a binary &lt;EM&gt;search&lt;/EM&gt; tree, because every parent is between its children. We might discuss properties of search trees later.)&lt;/P&gt;
&lt;P&gt;Pretty picture, but how are we going to represent this thing in code?&amp;nbsp; Suppose you’ve got a binary tree: in J&lt;I&gt;&lt;/I&gt;Script 
&lt;P&gt;&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;var mytree =&lt;BR&gt;{ &lt;BR&gt;&amp;nbsp; left:&lt;BR&gt;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; left: &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; left: null,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; value : "A", &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; right: null&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; value: "B",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; right: &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; left: null,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; value: "C",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; right: null&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; },&lt;BR&gt;&amp;nbsp; value:"E",&lt;BR&gt;&amp;nbsp; right :&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; left: null,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; value: "G",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; right:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; left: null, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; value: "H",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; right: null&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;};&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;Now we can use this recursive definition to write recursive functions that answer questions about this tree.&amp;nbsp; For the rest of this series I'll use as my motivating example one of the simplest questions you can ask about a binary tree: &lt;STRONG&gt;what is the deepest you can go in a given tree?&lt;/STRONG&gt;&amp;nbsp; &lt;/P&gt;
&lt;P&gt;We have a recursive definition, so come up with a recursive solution.&lt;/P&gt;
&lt;P&gt;What’s the base case?&amp;nbsp; An empty tree.&amp;nbsp; Clearly the deepest you can go in an empty tree is zero steps.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;What’s the recursive case? If you haven’t got an empty tree then you’ve got a value with two children.&amp;nbsp; Each child is itself a tree. The deepest you can go from this point is one (counting yourself), plus the depth of the deepest child. And we've got a function that gives you the depth of a tree, so let's call it on each child:&lt;/P&gt;&lt;FONT face="lucida console" color=navy&gt;
&lt;P&gt;function treeDepth(curtree) {&lt;BR&gt;&amp;nbsp; if (curtree == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;return 1 + Math.max(treeDepth(curtree.left), treeDepth(curtree.right));&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;It's magically delicious.&amp;nbsp; It's like having n dominoes lined up.&amp;nbsp; If you knock over the last one, and you know that every domino knocked over also knocks over the previous, then you know that they'll all go down eventually.&lt;/P&gt;
&lt;P&gt;Formally, we could use complete induction to show that this works for all trees.&amp;nbsp; We know that it works for trees of height zero. As an inductive hypothesis, assume that it works for trees of height &amp;lt;= k.&amp;nbsp; Since a tree of height k+1 has one subtree of height k and another of height &amp;lt;=k, by hypothesis the recursion correctly calculates their heights and computes the max as k+1, and we're done. (Of course, how do we know that complete induction works? That question takes us into Peano's Axioms and other topics in the foundations of mathematical logic.&amp;nbsp;Perhaps another time...)&lt;/P&gt;
&lt;P&gt;Next time: Trouble in paradise: the out-of-stack error rears its ugly head.&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=442590" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Rarefied+Heights/default.aspx">Rarefied Heights</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category></item><item><title>Recursion, Part Zero</title><link>http://blogs.msdn.com/ericlippert/archive/2005/07/25/recursion-part-zero.aspx</link><pubDate>Mon, 25 Jul 2005 13:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:442568</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/442568.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=442568</wfw:commentRss><description>&lt;FONT face="lucida sans unicode" color=purple size=2&gt;
&lt;P&gt;I’ve mentioned recursive programming techniques several times over the years in this blog (&lt;a href="http://blogs.msdn.com/ericlippert/archive/2004/03/16/90851.aspx"&gt;Topological Sort&lt;/A&gt;, &lt;a href="http://blogs.msdn.com/ericlippert/archive/2004/05/19/135392.aspx"&gt;How Not To Teach Recursion&lt;/A&gt;, &lt;a href="http://blogs.msdn.com/ericlippert/archive/2004/05/20/136327.aspx"&gt;Fibonacci Challenge&lt;/A&gt;, &lt;a href="http://blogs.msdn.com/ericlippert/archive/2004/07/21/189974.aspx"&gt;Recursion and Dynamic Programming&lt;/A&gt;, &lt;a href="http://blogs.msdn.com/ericlippert/archive/2004/09/27/234826.aspx"&gt;Sometimes Breadth Is Better Than Depth&lt;/A&gt;, and probably a few others).&amp;nbsp; A lot of developers, particularly those without a formal education in computer science, are still pretty vague on this weird idea of functions that call themselves.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;If you’re interviewing at Microsoft for a development position you can expect that at least one person will ask you a whiteboarding question that involves some kind of recursive problem. This isn’t because we’re a bunch of architecture astronauts or theory wonks, it’s because &lt;STRONG&gt;if you want to be a dev here, recursion is simply one of the tools that you have to have in your toolbox.&lt;/STRONG&gt; We use recursive data structures and algorithms quite a bit, and people are expected to know how they work.&lt;/P&gt;
&lt;P&gt;I’d therefore like to take this opportunity to do a series on some of the theory and practice of writing recursive and recursive-like functions. I want to show that (a) they're not as mysterious as they seem, &lt;STRONG&gt;but&lt;/STRONG&gt; (b) that they are potentially dangerous, and (c) there are &lt;STRONG&gt;some absolutely crazy-but-fun&lt;/STRONG&gt; techniques for turning a recursive program into a nonrecursive program.&amp;nbsp;Hopefully by the time we're done here your head will hurt, but hey, &lt;STRONG&gt;it builds character&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;I'm going to get as much of this done as possible and queued up, because I'm going to go dark shortly. I'm getting married in less than two weeks!&amp;nbsp;Between getting ready for that and finishing up stuff at work, I'm going to be swamped.&amp;nbsp;(And you'd better believe I'm not blogging about recursive programming techniques from my honeymoon.)&amp;nbsp; I'll be back in late August and things should pick up then.&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=442568" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Rarefied+Heights/default.aspx">Rarefied Heights</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category></item><item><title>Bad Recursion Revisited</title><link>http://blogs.msdn.com/ericlippert/archive/2005/04/28/bad-recursion-revisited.aspx</link><pubDate>Thu, 28 Apr 2005 21:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:413061</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>22</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/413061.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=413061</wfw:commentRss><description>&lt;FONT face="lucida sans unicode"&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;We have internal email lists for questions about programming languages. Here's one that came across recently that I thought illustrated a good point about language design. &lt;/P&gt;
&lt;P&gt;An interview candidate gave the following awful implementation of the factorial function. (Recall that factorial is notated "n!", and is defined as the product of all the integers from 1 to n. 0! is defined as 1. So 4! = 4 x 3 x 2 x 1 = 24.)&lt;/P&gt;
&lt;P&gt;If you note that n! = n x ((n-1)!) then a &lt;/FONT&gt;&lt;a href="http://blogs.msdn.com/ericlippert/archive/2004/05/19/135392.aspx"&gt;&lt;U&gt;&lt;FONT color=#0000ff size=2&gt;recursive solution&lt;/U&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#800080 size=2&gt; comes to mind. When asked to implement the factorial function in C, an interview candidate came up with this:&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;
&lt;P&gt;int F(int x){&lt;BR&gt;&amp;nbsp; return (x &amp;gt; 1) ? (x * F(--x)) : x;&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;Now, leaving aside for the moment the fact that &lt;/FONT&gt;&lt;a href="http://blogs.msdn.com/ericlippert/archive/2004/5/20.aspx"&gt;&lt;U&gt;&lt;FONT color=#0000ff size=2&gt;this&amp;nbsp;badly-named function&amp;nbsp;does no bounds checking on the inputs, potentially consumes the entire stack, returns a wrong or nonsensical answer for inputs less than one, and is a recursive solution to a problem that can easily be solved with a simple lookup table&lt;/U&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#800080 size=2&gt;, it has another big problem -- it doesn't even return the correct answer for any input greater than one either! F(4) will return 6, not 24, in Microsoft C. &lt;/P&gt;
&lt;P&gt;And yet the &lt;I&gt;seemingly&lt;/I&gt; equivalent C#, JScript and VBScript programs return 24.&lt;/P&gt;
&lt;P&gt;The question was "What the heck is up with that?" &lt;/P&gt;
&lt;P&gt;This looks perfectly straightforward. If x is 4, then we evaluate the consequence of the trinary operator. 4 * F(3) = 4 * 3 * F(2) = 4 * 3 * 2 * F(1) = 4 * 3 * 2 * 1 = 24, right? What is broken with C?&lt;/P&gt;
&lt;P&gt;Page 52 of K&amp;amp;R has the answer.&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;
&lt;P&gt;"C, like most languages, does not specify the order in which the operands of an operator are evaluated. (The exceptions are &amp;amp;&amp;amp;, ||, ?: and ','.) For example, in a statement like x = f()+g(); f may be evaluated before g or vice versa; thus if either f or g alters a variable on which the other depends, x can depend on the order of evaluation."&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;The Microsoft C compiler actually evaluates the function call first, which causes x to be decremented &lt;I&gt;before&lt;/I&gt; the multiplication. So this is actually the same as 3 * F(3) = 3 * 2 * F(1) = 3 * 2 * 1 = 6.&lt;/P&gt;
&lt;P&gt;Why does the specification call out that the compiler can choose any order for subexpression evaluation? Because then the compiler can choose to optimize the order so that it consumes a small number of stack or register slots for the results. &lt;/P&gt;
&lt;P&gt;Of course, C&amp;nbsp;was written back in the dark ages --&amp;nbsp;the 1970's&amp;nbsp;-- when indeed most languages were pretty ill-specified and full of terrible "gotchas" like this. JScript, VBScript, C#, and most modern languages do guarantee that functions will be evaluated in left-to-right order. In all these languages, &lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080&gt;x = f() + g() * h();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;will evaluate f, then g, then h.&lt;/P&gt;
&lt;P&gt;As K&amp;amp;R notes &lt;FONT color=#000000&gt;"The moral is that writing code that depends on order of evaluations is a bad programming practice in any language."&lt;/FONT&gt;&amp;nbsp; Amen to that!&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=413061" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/VBScript/default.aspx">VBScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Code+Quality/default.aspx">Code Quality</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/precedence/default.aspx">precedence</category></item><item><title>Breadth is sometimes better than depth</title><link>http://blogs.msdn.com/ericlippert/archive/2004/09/27/breadth-is-sometimes-better-than-depth.aspx</link><pubDate>Mon, 27 Sep 2004 17:58:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:234826</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>16</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/234826.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=234826</wfw:commentRss><description>&lt;font face="lucida sans unicode"&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;A while back the &lt;/font&gt;&lt;A href="http://blogs.msdn.com/gstemp"&gt;&lt;u&gt;&lt;font color="#0000ff" size="2"&gt;Scripting Guys&lt;/u&gt;&lt;/font&gt;&lt;/a&gt;&lt;font color="#800080" size="2"&gt; blogged about &lt;/font&gt;&lt;A href="http://blogs.msdn.com/gstemp/archive/2004/08/10/212113.aspx"&gt;&lt;u&gt;&lt;font color="#0000ff" size="2"&gt;using recursion to list all the files in a directory&lt;/u&gt;&lt;/font&gt;&lt;/a&gt;&lt;font color="#800080" size="2"&gt; and all its subdirectories. Something that you'll notice about this very standard solution to this problem is that it is "depth first". That is, it lists the files like this:&lt;/p&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt; &lt;p&gt;c:\xyz.txt&lt;br /&gt;c:\foo\bbb.txt&lt;br /&gt;c:\foo\abc\def.txt&lt;br /&gt;c:\foo\bar\baz.txt&lt;br /&gt;c:\foo\bar\blah.txt&lt;br /&gt;c:\qaz\zaq.txt&lt;br /&gt;c:\qaz\lll\ggg.txt&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;It picks a branch and follows it down the tree as far as it can, listing directories as it goes, retreats back up as &lt;b&gt;little as possible&lt;/b&gt;, picks another branch to go down, goes as far down it as possible, and so on, until the entire tree has been explored. You can see why this is called "depth first".&lt;/p&gt; &lt;p&gt;You don't &lt;i&gt;need&lt;/i&gt; to use recursion to do this; recursion is just an elegant way to solve the problem. The essence of the algorithm is that information about the next node to process is stored in a &lt;b&gt;stack&lt;/b&gt;. The algorithm is simple: pop the stack, process the directory, push all the subdirectories onto the stack, repeat until the stack is empty. Recursion just lets you do this algorithm without making the stack explicit; the stack is the call stack and &lt;em&gt;doing the recursive call pushes a new frame on the call stack for you&lt;/em&gt;. We can easily do this without recursion by making the stack explicit:&lt;/p&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt; &lt;p&gt;var FSO = new ActiveXObject("Scripting.FileSystemObject");&lt;br /&gt;var stack = new Array();&lt;br /&gt;stack.push(FSO.GetFolder("."));&lt;br /&gt;while(stack.length &amp;gt; 0)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; var folder = stack.pop();&lt;br /&gt;&amp;nbsp; for (var enumtor = new Enumerator(folder.Subfolders) ; !enumtor.atEnd(); enumtor.moveNext())&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stack.push(enumtor.item());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(e){}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp; for (enumtor = new Enumerator(folder.Files) ; !enumtor.atEnd(); enumtor.moveNext())&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WScript.Echo(enumtor.item().Path);&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(e){}&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;Notice that I've wrapped the file manipulation code in try-catches. As I've &lt;/font&gt;&lt;A href="http://blogs.msdn.com/ericlippert/archive/2004/08/25/220373.aspx"&gt;&lt;u&gt;&lt;font color="#0000ff" size="2"&gt;mentioned before&lt;/u&gt;&lt;/font&gt;&lt;/a&gt;&lt;font color="#800080" size="2"&gt;, in this script if there is a problem reading a file -- like, I don't own it and therefore I get a security violation -- I want to skip the problem and continue on. I do not want to write robust error handling for this trivial one-off script.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#800080" size="2"&gt;The other day I had a problem -- a few weeks earlier I had written a little test program and stuck it in a directory somewhere very near the top of my directory hierarchy, but I couldn't remember where exactly. I already had the depth-first program above, and could easily modify it to add a regular expression search of each file looking for a pattern. But there are some &lt;b&gt;very&lt;/b&gt; deep directories on that drive where I knew there would be no matches, but would take a lot of time to search. I could have written code to omit those directories, but there was another way to solve this problem: since I knew that the file was going to be somewhere shallow, don't do a depth-first search in the first place. Do a &lt;b&gt;breadth-first&lt;/b&gt; search. That is, search all the files in the top level, then all the files that are one deep, then all the files that are two deep, then three deep, and so on.&lt;/p&gt; &lt;p&gt;The nice thing is that it's basically the same algorithm, just with a minor change. Instead of doing a last-in-first-out stack, we'll just do a first-in-first-out queue and magically get a breadth-first traversal:&lt;/p&gt; &lt;p&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt;var FSO = new ActiveXObject("Scripting.FileSystemObject");&lt;br /&gt;var queue = new Array();&lt;br /&gt;queue[queue.length] = FSO.GetFolder(".");&lt;br /&gt;var counter = 0;&lt;br /&gt;while(counter &amp;lt; queue.length)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; var folder = queue[counter];&lt;br /&gt;&amp;nbsp; for (var enumtor = new Enumerator(folder.Subfolders) ; !enumtor.atEnd(); enumtor.moveNext())&lt;br /&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt;try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; queue[queue.length] = enumtor.item();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(e) {}&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; for (enumtor = new Enumerator(folder.Files) ; !enumtor.atEnd(); enumtor.moveNext())&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp; try&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; WScript.Echo(enumtor.item().Path);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(e){}&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; queue[counter] = null;&lt;br /&gt;&amp;nbsp; counter++;&lt;br /&gt;}&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;This then puts out the files in the order&lt;/p&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt; &lt;p&gt;c:\xyz.txt&lt;br /&gt;c:\qaz\zaq.txt&lt;br /&gt;c:\foo\bbb.txt&lt;br /&gt;c:\qaz\lll\ggg.txt&lt;br /&gt;c:\foo\abc\def.txt&lt;br /&gt;c:\foo\bar\baz.txt&lt;br /&gt;c:\foo\bar\blah.txt&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;going from shallowest to deepest gradually rather than continually diving way down and then coming back up.&lt;/p&gt;&lt;/font&gt;&lt;/font&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=234826" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category></item><item><title>Recursion and Dynamic Programming</title><link>http://blogs.msdn.com/ericlippert/archive/2004/07/21/recursion-and-dynamic-programming.aspx</link><pubDate>Wed, 21 Jul 2004 16:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:189974</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/189974.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=189974</wfw:commentRss><description>&lt;P&gt;&lt;FONT face="Times New Roman" size=3&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Back in May &lt;A title=http://blogs.msdn.com/ericlippert/archive/2004/05/20/136327.aspx href="http://blogs.msdn.com/ericlippert/archive/2004/05/20/136327.aspx"&gt;we were discussing the merits and drawbacks of recursive programming techniques&lt;/A&gt; -- that is, writing functions which break down problems into sub-problems, and then call themselves.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The drawback of such an approach is that in some cases, you end up doing way more work than necessary.&amp;nbsp; The example I used was the na&amp;#239;ve Fibonacci algorithm:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;function fib(n) {&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (n == 1 || n == 2)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 1;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return fib(n-1) + fib(n-2);&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;}
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;This is an &lt;B&gt;&lt;SPAN&gt;exponential&lt;/SPAN&gt;&lt;/B&gt; algorithm -- calculating the first few numbers is very cheap, but once we get up into the tens and twenties, you very quickly end up doing millions of recursive steps.&amp;nbsp; Something that you might notice is that since &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib(20)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; cannot possibly need to calculate more than 19 distinct previous fib values, that most of those millions of calculations are the same ones being done over and over again.&amp;nbsp; &amp;nbsp;(ASIDE: This seemingly obvious argument has a name: the &lt;B&gt;&lt;SPAN&gt;&lt;A title=http://en.wikipedia.org/wiki/Pigeonhole_principle href="http://en.wikipedia.org/wiki/Pigeonhole_principle"&gt;Pigeonhole Principle&lt;/A&gt;&lt;/SPAN&gt;&lt;/B&gt;.)
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Therefore, there's a way to keep this recursive AND make it efficient: don't recompute a result you already know!&amp;nbsp; How about this?
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;var fibarr = new Array(0, 1, 1);&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;function fib(n) {&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (fibarr[n] == null)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fibarr[n] = fib(n-1) + fib(n-2);&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return fibarr[n];&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;}
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;All of a sudden our formerly exponential algorithm has become linear if &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;n&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; has not already been calculated, and constant if it has. The time performance gets a huge win, but does so at a cost -- &lt;B&gt;&lt;SPAN&gt;it chews up memory to store the results&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; It's a pretty small cost though compared to the win.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;This technique of taking an inefficient algorithm and improving its performance by storing and reusing earlier results is called &lt;B&gt;&lt;SPAN&gt;&lt;A title=http://www.nist.gov/dads/HTML/memoize.html href="http://www.nist.gov/dads/HTML/memoize.html"&gt;memoization&lt;/A&gt;&lt;/SPAN&gt;&lt;/B&gt; or &lt;B&gt;&lt;SPAN&gt;&lt;A title=http://www.nist.gov/dads/HTML/dynamicprog.html href="http://www.nist.gov/dads/HTML/dynamicprog.html"&gt;dynamic&lt;SPAN title=http://www.nist.gov/dads/HTML/dynamicprog.html&gt; &lt;/SPAN&gt;programming&lt;/A&gt;&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; Dynamic programming isn't hard, but a lot of script programmers don't know about this powerful technique, so I thought I might talk about it a bit today.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;(ASIDE: Some would draw the subtle distinction that "dynamic programming" specifically means &amp;#8220;using memoization to solve &lt;I&gt;&lt;SPAN&gt;optimization&lt;/SPAN&gt;&lt;/I&gt; problems&amp;#8221;&amp;nbsp;-- but I wouldn't.&amp;nbsp; Note also that this term predates its use in the context of &lt;I&gt;&lt;SPAN&gt;computer&lt;/SPAN&gt;&lt;/I&gt; programming.&amp;nbsp; The mathematician Richard Bellman originated the term in the 1950's -- he was studying the behaviour of &lt;A title=http://www-anw.cs.umass.edu/~rich/book/4/node1.html href="http://www-anw.cs.umass.edu/~rich/book/4/node1.html"&gt;Markovian systems&lt;/A&gt;.&amp;nbsp; However, for my purposes I'm going to ignore the historical link between dynamic programming and the probability problems it was invented to solve, and talk just about the recursive programming applications of the technique.)
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I started thinking about this because recently someone asked me how "diff" algorithms work -- you know, those programs that take two text files and show you what the differences and commonalities are.&amp;nbsp; There are lots of different "diff" algorithms, and some of them use dynamic programming techniques. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Here's a related problem: determine the &lt;B&gt;&lt;SPAN&gt;longest common subsequence&lt;/SPAN&gt;&lt;/B&gt; of two arrays.&amp;nbsp; Let me clarify what exactly I mean by that.&amp;nbsp; Consider the following lists:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;var original = new Array("jackdaws", "love", "my", "big", "sphinx", "of", "quartz");&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;var modified = new Array("some", "big", "jackdaws", "love", "my", "sphinx", &amp;nbsp;"of", "quartz");
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;We want the &lt;B&gt;&lt;SPAN&gt;longest&lt;/SPAN&gt;&lt;/B&gt; sequence of items that are found in both sets &lt;B&gt;&lt;SPAN&gt;in the same order&lt;/SPAN&gt;&lt;/B&gt;. Here the longest common subsequence would be "&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;jackdaws", "love", "my", "sphinx", "of", "quartz"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; &amp;nbsp;The "big" isn't in the same order with respect to the rest of the subsequence, so it does not appear in the longest common subsequence.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I'm sure you can see how this pertains to the "diff" problem -- if you know the longest common subsequence then it makes sense that it would be the "in common" part, and everything that is not in the longest common subsequence is in the "things that have changed" part.&amp;nbsp; (Of course, diff algorithms usually operate on lines of text, not on individual words, but the difference is irrelevant, so we'll stick with words for the sake of the example.&amp;nbsp; Also, there are more sophisticated diff algorithms, which I won't go into today.)
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;How do we solve this problem?&amp;nbsp; We could start by noticing that &lt;B&gt;&lt;SPAN&gt;if the two sequences&lt;/SPAN&gt;&lt;/B&gt; &lt;B&gt;&lt;SPAN&gt;start with the same word&lt;/SPAN&gt;&lt;/B&gt;, &lt;B&gt;&lt;SPAN&gt;then the longest common subsequence always contains that word&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; We can automatically put that word on our list, and we've just reduced the problem to finding the longest common subset of the rest of the two lists.&amp;nbsp; We've made the problem smaller, which is goodness.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;But if the two lists do not begin with the same word, then one or both of them is not on the longest list. &amp;nbsp;But one of them might be. How do we determine which one, if any, to add?&amp;nbsp; Try it both ways and see!&amp;nbsp; Either way, the two sub-problems are manipulating smaller lists, so we know that the recursion will eventually terminate.&amp;nbsp; Whichever trial results in the longer common subsequence is the winner. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Instead of "throwing it away" by deleting the item from the array, instead let's just write a routine that finds the longest common subsequence that exists &lt;B&gt;&lt;SPAN&gt;after a particular starting point in both arrays&lt;/SPAN&gt;&lt;/B&gt;. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Here's a solution without memoization:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;function LongestCommonSubsequence(arr1, arr2)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return LCS(0, 0);&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;function LCS(start1, start2)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var result;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var remainder1;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var remainder2;&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;// If we're at the end of either list, then the longest subsequence is empty
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (start1 == arr1.length || start2 == arr2.length)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new Array();&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (arr1[start1] == arr2[start2])&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;// If the start element is the same in both, then it is on the LCS, so&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;// we'll just recurse on the remainder of both lists.&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = new Array();&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result[0] = arr1[start1];&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = result.concat(LCS(start1 + 1, start2 + 1));&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;// We don't know which list we should discard from.&amp;nbsp; &lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;// Try both ways, pick whichever is better.&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; remainder1 = LCS(start1 + 1, start2);&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; remainder2 = LCS(start1, start2 + 1);&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (remainder1.length &amp;gt; remainder2.length)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = remainder1;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;result = remainder2;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return result;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;}&lt;BR&gt;}
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;This algorithm works, but holy cow is it ever inefficient!&amp;nbsp; If the two arrays are both around n items long then this turns out to be exponential, for the same reason that the na&amp;#239;ve fib implementation was exponential&lt;B&gt;&lt;SPAN&gt;.&amp;nbsp; It recalculates the same subsequences over and over again&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; In this particular example there are 2410 recursions to find the LCS of a seven and an eight item array!&amp;nbsp; Clearly there are only 56 possible "start1" and "start2" combinations to try, so by the Pigeonhole Principle there must be &lt;I&gt;&lt;SPAN&gt;massive&lt;/SPAN&gt;&lt;/I&gt; re-calculation going on here.&amp;nbsp; If the arrays get longer, this algorithm&amp;nbsp;blows up enormously.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;We can do a lot better, using the same technique as we used above.&amp;nbsp; Every time we solve a subproblem, we make a note of the solution.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;function LongestCommonSubsequence(arr1, arr2)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var solutions = {};&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return LCS(0, 0);&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;function LCS(start1, start2)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var result;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var remainder1;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var remainder2;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var index = start1 + "," + start2;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (solutions[index] != null)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return solutions[index];&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // [blah blah blah, same as above&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;]&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; solutions[index] = result;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return result;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;}&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Which only does 82 recursions.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If you were &lt;I&gt;&lt;SPAN&gt;really&lt;/SPAN&gt;&lt;/I&gt; being clever, you might notice that the recursive solution &lt;B&gt;&lt;SPAN&gt;eventually fills in almost the entire solution array&lt;/SPAN&gt;&lt;/B&gt;, and only ever looks "up" from the current position, so you might as well simply write an &lt;B&gt;&lt;SPAN&gt;iterative&lt;/SPAN&gt;&lt;/B&gt; program that fills in the solution array &lt;B&gt;&lt;SPAN&gt;backwards&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;A downside of this particular implementation is that it chews up rather a lot of memory -- on the order of n^2 extra arrays in the solutions table, many of which are potentially a sizable fraction of the inputs.&amp;nbsp; But i&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;n fact there are ways to use dynamic programming more aggressively to solve this problem using much less memory.&amp;nbsp; There are ways to solve this problem that only require storing the &lt;B&gt;&lt;SPAN&gt;lengths&lt;/SPAN&gt;&lt;/B&gt; of the subsequences, rather than the subsequences themselves, and there are ways to "throw away" some of the stored results as you no longer need them.&amp;nbsp; That would eliminate a lot of work -- constructing the subsequence arrays isn't cheap.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;However, I don't want to get into that level of detail on this particular problem.&amp;nbsp; Clearly, dynamic programming is a huge topic, and this just gives a brief taste. My point is simply that &lt;B&gt;&lt;SPAN&gt;caching the solutions of problems you've already solved gives a potentially huge performance win, particularly when doing recursive calculations.&amp;nbsp; &lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=189974" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Rarefied+Heights/default.aspx">Rarefied Heights</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category></item><item><title>Results Of The Fibonacci Challenge Are In</title><link>http://blogs.msdn.com/ericlippert/archive/2004/05/20/results-of-the-fibonacci-challenge-are-in.aspx</link><pubDate>Fri, 21 May 2004 00:11:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:136327</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/136327.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=136327</wfw:commentRss><description>&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Another bunch of good replies to my challenge of yesterday.&amp;nbsp; And again, a bunch of answers that I didn't expect, and some of the points that I was thinking of weren't mentioned. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;People seem to like this more conversational format; I'll probably use it more in the future. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Three&amp;nbsp;readers had conjectures as to the running time of &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_1&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, the recursive algorithm.&amp;nbsp; Deriving the asymptotic order is pretty straightforward.&amp;nbsp; There must be some function &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;f(n)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; such that &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_1&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; is &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(f(n))&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; Well, what are the costs?&amp;nbsp; It's trivially true that &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_1(1)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; is &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(1)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, and so is &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_1(2)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; Let's therefore say that &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;f(1) = 1&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; and &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;f(2) = 1&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;What's the cost of the algorithm for large &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;n&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;?&amp;nbsp; Well, there's a constant bit at the beginning with the comparison, and a constant cost in the addition, but we can neglect those.&amp;nbsp; The real work is done in the recursion.&amp;nbsp;&amp;nbsp;Clearly &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(f(n)) = O(f(n-2) + O(f(n-1)) 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;That looks familiar!&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;f(n) = fib(n)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, so &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_1&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; is &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(fib(n))&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;We&amp;#8217;ve&amp;nbsp;established the truth of Frederik Slijkerman's comment that &lt;STRONG&gt;recursive fib has a running time proportional to the size of its output&lt;/STRONG&gt;.&amp;nbsp; Steven Bone conjectured that recursive fib was &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(2&lt;SUP&gt;n&lt;/SUP&gt;)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; He was also right -- almost.&amp;nbsp; How is that possible? 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The definition of the Fibonacci numbers&amp;nbsp;that I&amp;nbsp;gave is called a "recurrence relation". &amp;nbsp;Let me define two more recurrences: 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;s(1) = s(2) = 1, &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;s(n) = s(n-2) + s(n-2)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;f(1) = f(2) = 1, &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;f(n) = f(n-2) + f(n-1)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;b(1) = b(2) = 1, &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;b(n) = b(n-1) + b(n-1) 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;You agree that it is clear that &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;s(n) &amp;lt;= f(n) &amp;lt;= b(n)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, right?&amp;nbsp;&amp;nbsp;The first sequence is &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;1, 1, 2, 2, 4, 4, 8, 8, 16, 16...&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&amp;nbsp; which grows at&amp;nbsp;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(SQRT(2)&lt;SUP&gt;n&lt;/SUP&gt;)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; The second sequence is &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;1, 1, 2, 4, 8, 16, 32, ...&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&amp;nbsp; which&amp;nbsp;clearly&amp;nbsp;grows at &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(2&lt;SUP&gt;n&lt;/SUP&gt;)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;f&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; is &lt;B&gt;&lt;SPAN&gt;sandwiched &lt;/SPAN&gt;&lt;/B&gt;between two functions that grow at &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(something&lt;SUP&gt;n&lt;/SUP&gt;)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=purple size=2&gt;&lt;SPAN&gt; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;so it must also be &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(something&lt;SUP&gt;n&lt;/SUP&gt;)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;!&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The exact constant doesn't really matter for our purposes.&amp;nbsp;It's actually about &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(1.6&lt;SUP&gt;n&lt;/SUP&gt;)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; Yes, I'm handwaving here.&amp;nbsp; A more precise definition of order notation would make it clear when two functions are asymptotically equivalent, but that's a subject for another day.&amp;nbsp; There are different notations for functions with asymptotic upper, lower, and strict approximations, but I don't want to get into that now. The point is that this thing grows way faster than any polynomial in the long run and, more important, grows&amp;nbsp;&lt;STRONG&gt;extremely quickly&lt;/STRONG&gt; even in the short run. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Clearly &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_1&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; consumes &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(n)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; memory off the stack.&amp;nbsp; Equally clearly, &amp;nbsp;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_2&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; is &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(n)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; and consumes &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(1)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; memory.&amp;nbsp; I hinted that there was an &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(1)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; solution.&amp;nbsp; Indeed there is, provided that we more carefully define the problem.&amp;nbsp; Before I get to it, I mentioned that I often ask about robustness in interviews.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Clearly it's a good idea to make sure that &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;n&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; is one or larger; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_2&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; goes into an infinite loop if it isn't.&amp;nbsp; But that's certainly not all!&amp;nbsp;&amp;nbsp;What's the actual vs. desired output of 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_2();&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_2(1, 2, 3)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_2("2B||!2B");&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_2("hello, world!");&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_2(null);&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_2(3.14159);&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_2(new Date()); 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;and so on?&amp;nbsp; None of those make much sense and some of them go into infinite loops.&amp;nbsp;Remember, JScript isn't C++ in fancy dress.&amp;nbsp; It's not a statically typed language, so if you have type restrictions, you're going to have to write a bunch of runtime code, or use a different language. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Furthermore, clearly there is a sensible lower bound of one.&amp;nbsp; Is there a sensible upper bound?&amp;nbsp; I note that 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib_2(77)&amp;nbsp;--&amp;gt;&amp;nbsp;&amp;nbsp; 552793970088475&lt;FONT color=#ff0000&gt;7&lt;/FONT&gt;&lt;BR&gt;fib_2(78)&amp;nbsp;--&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;894439432379146&lt;FONT color=#ff0000&gt;4&lt;/FONT&gt;&lt;BR&gt;fib_2(79)&amp;nbsp;--&amp;gt;&amp;nbsp; 1447233402467622&lt;FONT color=#ff0000&gt;0&lt;/FONT&gt; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;How do&amp;nbsp;we add together a number ending in 7 and a number ending in 4 and end up with an even number?&amp;nbsp; &lt;STRONG&gt;We've run out of precision&lt;/STRONG&gt;.&amp;nbsp; A floating point number only has 53 bits of precision; as soon as the value exceeds 2&lt;SUP&gt;53&lt;/SUP&gt;, we start dropping bits off the end and therefore start returning incorrect results. &amp;nbsp;I asked for a function that produced the nth Fibonacci number, not one that produced a &lt;B&gt;&lt;SPAN&gt;close approximation&lt;/SPAN&gt;&lt;/B&gt; of it!&amp;nbsp; That's a point which a good interview candidate would clarify.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Assuming that we really do need exact numbers, and assuming further that the caller is willing to accept the limitations on precision that an IEEE float imposes, this method only has 78 sensible inputs -- the first 78 positive integers.&amp;nbsp; Therefore it only has 78 possible outputs.&amp;nbsp; When I hear that a method only has 78 outputs and the inputs are integers, I like table driven solutions.&amp;nbsp; (If we were using some other language that had 64 bit or 32 bit integers, the limits would be different, but they'd still be small enough to make a table-driven solution feasible.) 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;var fibarr = new Array(null, 1, 1, 2, 3, 5, /*[...]*/, 8944394323791464);&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;function fib_3(n)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=purple size=2&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;// [appropriate checking here.]&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=purple size=2&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;return fibarr[n];&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;} 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;That's certainly &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;O(1).&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If those aren't sensible restrictions, then we have waaaaay more work to do.&amp;nbsp; We need to figure out what the restrictions are, then write a numeric computation library that handles numbers up to the precision we need, and so on.&amp;nbsp; That introduces a whole other set of costs which we'd have to analyze on a case by case basis.&amp;nbsp;&amp;nbsp;If we really did have to handle arbitrarily big numbers then&amp;nbsp;a well-implemented algorithm would&amp;nbsp;probably end up being &lt;SPAN&gt;&lt;FONT face="Lucida Console" color=#000080&gt;O(log n)&lt;/FONT&gt;&lt;/SPAN&gt;. Several people mentioned Binet's Formula, which we could use. However, the mathematics of&amp;nbsp;all that&amp;nbsp;is more than I want to tackle in today's blog entry; I have work to do.&lt;/SPAN&gt;&lt;/FONT&gt; 
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If the caller really, really wanted this to be as fast as possible in raw speed terms, not algorithmic complexity terms, then we have to start talking about what we can change.&amp;nbsp; Language?&amp;nbsp; Seems to me that a C++ or assembly&amp;nbsp;language&amp;nbsp;implementation is going to be faster all around.&amp;nbsp; What hardware are we stuck with?&amp;nbsp; How big is the processor cache?&amp;nbsp; Will the table fit into it?&amp;nbsp; Can we hint to the compiler that the table is read-only after it is constructed and eke out more speed somehow?&amp;nbsp; What are these numbers being used for anyway, and how do we know that this method is&amp;nbsp;even the bottleneck? 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Finally, Dan Shappir mentioned tail recursion and lazy evaluation using a zipper function on an infinite list.&amp;nbsp; That's quite coincidental; a couple days ago coworker of mine&amp;nbsp;showed me a problem from an old ACM contest he'd been working on for fun. The problem was&amp;nbsp;to implement a particular subset of Haskell's infinite list and zipper function capabilities. Which got me thinking that there are lots of interesting programming ideas that I&amp;nbsp;could blog about.&amp;nbsp; Perhaps I'll take up some of that stuff in the coming weeks. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=136327" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category></item><item><title>How Not To Teach Recursion</title><link>http://blogs.msdn.com/ericlippert/archive/2004/05/19/how-not-to-teach-recursion.aspx</link><pubDate>Thu, 20 May 2004 01:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:135392</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>63</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/135392.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=135392</wfw:commentRss><description>&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;A &lt;A title=http://www.joelonsoftware.com/ href="http://www.joelonsoftware.com/" mce_href="http://www.joelonsoftware.com/"&gt;Joel On Software&lt;/A&gt; reader asked the other day for examples of recursive functions other than old chestnuts like Fibonacci or factorial.&amp;nbsp; Excellent question. I suggested &lt;A title=http://blogs.msdn.com/ericlippert/archive/2004/03/16/90851.aspx href="http://blogs.msdn.com/ericlippert/archive/2004/03/16/90851.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2004/03/16/90851.aspx"&gt;topological sort&lt;/A&gt;, of course, but there are plenty of other examples that are way better than the Fibonacci numbers.&amp;nbsp; Why do I think Fibonacci is bad?&amp;nbsp; Read on. 
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;In case it's slipped your mind, the Fibonacci numbers are defined as follows: &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib(1) = 1&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib(2) = 1&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fib(n) = fib(n-1) + fib(n-2) &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;thus, they go 1, 1, 2, 3, 5, 8, 13, 21, … &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The Fibonacci numbers have many interesting properties.&amp;nbsp; For example, suppose you have a pair of rabbits that every year gives birth to a pair of rabbits, rabbits take one year to reach maturity, and rabbits never die.&amp;nbsp; In that (admittedly unrealistic) situation, the number of pairs alive at any given time is a Fibonacci number.&amp;nbsp; Clearly the number alive this year is the number alive the year before (who all live) plus the number alive two years before (who are now mature enough to breed.)&amp;nbsp; Fibonacci numbers also have a relationship to the Golden Mean, logarithmic spirals,&amp;nbsp;and many other interesting nooks of mathematics.&amp;nbsp; But that's not what I want to talk about today. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Because they have a straightforward recursive definition, it's natural to introduce recursive programming to students by simply translating the definition into code: &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;function fib_1(n)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (n == 1 || n == 2)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;else&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return fib_1(n-1) + fib_1(n-2);&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;} &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I am &lt;STRONG&gt;in principle&lt;/STRONG&gt; very much for this pedagogic approach.&amp;nbsp; Recursive programming can be difficult to get your head around.&amp;nbsp; Starting with recursive definitions, getting your head around those, and then using those definitions in code is a pretty good way to approach the material.&amp;nbsp; If you think of lists as being "zero or more items in a row", it is conceptually hard to think of anything other than an iterative approach to processing the list.&amp;nbsp; If you think of a list as "a list may be empty, or may be an item followed by a list", then the definition of the data leads itself to a recursive programming approach very naturally. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;STRONG&gt;Practically&lt;/STRONG&gt; however, this is probably the worst possible simple way to solve the Fibonacci problem.&amp;nbsp; When you introduce recursion by using it to solve a problem which iteration solves much, much better, students come away thinking that recursion is dumb -- that it is both harder to understand and produces worse solutions.&amp;nbsp; Better to pick an example where the iterative solution is not better! &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;In fact, this is a good &lt;A href="http://blogs.msdn.com/ericlippert/archive/2004/04/15/114094.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2004/04/15/114094.aspx"&gt;whiteboarding question &lt;/A&gt;for interviews:&amp;nbsp; implement me a recursive Fibonacci algorithm, tell me why it is terrible, and write me a better algorithm. A good candidate should be able to come up with the above and something like this: &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;function fib_2(n)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (n == 1 || n == 2)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 1;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var fibprev = 1;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var fib = 1;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (var cur = 2 ; cur &amp;lt; n ; ++cur)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var temp = fib;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fib += fibprev;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fibprev = temp;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return fib;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;} &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Typical questions that I might ask at this point in an interview are &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;What are the asymptotic running time and memory usage of the two algorithms you've written?&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Can you write me an algorithm with even better asymptotic running time and memory usage?&amp;nbsp;Alternatively, can you convince me that&amp;nbsp;this is&amp;nbsp;as good as it gets?&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Suppose I asked you to make this algorithm absolutely as fast as possible.&amp;nbsp; What would you do?&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Now suppose that I do not&amp;nbsp;care&amp;nbsp;much about raw speed but I do want the method to be robust in the face of bad input.&amp;nbsp; Now what do you do?&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;and so on.&amp;nbsp; (Anyone who cares to propose answers to these can leave comments; consider this a spoiler warning if you want to work them out for yourself.&amp;nbsp; Working out the asymptotic&amp;nbsp;running time of recursive fib is quite easy and produces a somewhat surprising result.)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Another old chestnut that's often used as an introduction to recursion is the famous &lt;STRONG&gt;Tower Of Hanoi&lt;/STRONG&gt; problem.&amp;nbsp; Briefly stated, you have a number of disks with a hole in the middle, and three spikes upon which you can place disks.&amp;nbsp; The disks are all of different sizes and are arranged from biggest to smallest in a pyramid on one spike.&amp;nbsp; You must move one disk at a time from spike to spike, you must never place a larger disk on top of a smaller disk, and you must end up with the entire pyramid on a different spike than you started with.&amp;nbsp; &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The recursive solution is straightforward.&amp;nbsp; Moving a "sub-pyramid" of size one is obviously trivial.&amp;nbsp; To move a sub-pyramid of size n, first move a sub-pyramid of size n-1 to an&amp;nbsp; extra spike.&amp;nbsp; Then move the bottommost disk of the size n pyramid to the other extra spike.&amp;nbsp; Then move the sub-pyramid of size n-1 onto the disk on the second extra spike.&amp;nbsp; A nice recursive solution! &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Many recursive implementations for this old chestnut exist.&amp;nbsp; But I'm not a big fan of this problem as a pedagogic approach to recursion for two reasons.&amp;nbsp; First, it's &lt;STRONG&gt;totally contrived&lt;/STRONG&gt; (as is “fib“).&amp;nbsp; Second, there is a very simple iterative solution for this problem, which is almost never mentioned when it is used as an example of the power of recursive programming!&amp;nbsp; Again, we should pick examples where recursion is &lt;STRONG&gt;clearly&lt;/STRONG&gt; preferable. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;In case you're curious, the iterative solution can be produced by writing a program that implements these rules in a loop: &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Number the disks 1 to n starting from the top.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Never move an odd disk onto an odd disk.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Never move an even disk onto an even disk.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Never move a larger disk onto a smaller disk.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Never move the same disk twice in a row.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Never move a disk onto an empty spike unless you have to.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Move disks until there are no legal moves.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If you don't believe me, try it yourself with ace through ten of a deck of cards sometime.&amp;nbsp; Or, perhaps start with ace through four -- ace through ten will take you a while.&amp;nbsp; Both the recursive and iterative solutions are optimal in the number of moves.&amp;nbsp; The recursive solution is O(n) in terms of memory usage, the iterative solution is O(1).&lt;/SPAN&gt;&lt;/FONT&gt; &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=135392" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Recursion/default.aspx">Recursion</category></item></channel></rss>