Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1181 lines (941 sloc) 144 KB
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>8 Refactoring Methods with Recursive Combinators</title>
<link href="stylesheet.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="leanpub-main">
<h2 section-num="8" id="refactoring-methods-with-recursive-combinators"><span class="section-number">8 </span>Refactoring Methods with Recursive Combinators</h2>
<p>In previous chapters, we have met some of Combinatory Logic&#x2019;s most interesting combinators like the Kestrel, Thrush, Cardinal, Quirky Bird, and Bluebird. Today we are going to learn how combinators can help us separate the general form of an algorithm like &#x201C;divide and conquer&#x201D; from its specific concrete steps. Consider the method <code>#sum_squares</code>: It sums the squares of a tree of numbers, represented as a nested list.</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">def</code> <code class="n">sum_squares</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="k">if</code> <code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code>
<code class="n">value</code><code class="p">.</code><code class="n">map</code> <code class="n">do</code> <code class="o">|</code><code class="n">sub_value</code><code class="o">|</code>
<code class="n">sum_squares</code><code class="p">(</code><code class="n">sub_value</code><code class="p">)</code>
<code class="k">end</code><code class="p">.</code><code class="n">inject</code><code class="p">()</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="p">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="p">}</code>
<code class="k">else</code>
<code class="n">value</code> <code class="o">**</code> 2
<code class="k">end</code>
<code class="k">end</code>
<code class="n">p</code> <code class="n">sum_squares</code><code class="p">([</code>1<code class="p">,</code> 2<code class="p">,</code> 3<code class="p">,</code> <code class="p">[[</code>4<code class="p">,</code>5<code class="p">],</code> 6<code class="p">],</code> <code class="p">[[[</code>7<code class="p">]]]])</code>
<code class="p">=</code><code class="o">&gt;</code> 140
</pre></div>
</div>
<p>And the method <code>#rotate</code>: It rotates a square matrix, provided the length of each side is a power of two:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">def</code> <code class="n">rotate</code><code class="p">(</code><code class="n">square</code><code class="p">)</code>
<code class="k">if</code> <code class="n">square</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code> <code class="o">&amp;&amp;</code> <code class="n">square</code><code class="p">.</code><code class="nb">size</code> <code class="o">&gt;</code> 1
<code class="n">half_sz</code> <code class="p">=</code> <code class="n">square</code><code class="p">.</code><code class="nb">size</code> <code class="o">/</code> 2
<code class="n">sub_square</code> <code class="p">=</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">row</code><code class="p">,</code> <code class="n">col</code><code class="o">|</code>
<code class="n">square</code><code class="p">.</code><code class="n">slice</code><code class="p">(</code><code class="n">row</code><code class="p">,</code> <code class="n">half_sz</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">a_row</code><code class="o">|</code> <code class="n">a_row</code><code class="p">.</code><code class="n">slice</code><code class="p">(</code><code class="n">col</code><code class="p">,</code> <code class="n">half_sz</code><code class="p">)</code> <code class="p">}</code>
<code class="k">end</code>
<code class="n">upper_left</code> <code class="p">=</code> <code class="n">rotate</code><code class="p">(</code><code class="n">sub_square</code><code class="p">.</code><code class="n">call</code><code class="p">(</code>0<code class="p">,</code>0<code class="p">))</code>
<code class="n">lower_left</code> <code class="p">=</code> <code class="n">rotate</code><code class="p">(</code><code class="n">sub_square</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">half_sz</code><code class="p">,</code>0<code class="p">))</code>
<code class="n">upper_right</code> <code class="p">=</code> <code class="n">rotate</code><code class="p">(</code><code class="n">sub_square</code><code class="p">.</code><code class="n">call</code><code class="p">(</code>0<code class="p">,</code><code class="n">half_sz</code><code class="p">))</code>
<code class="n">lower_right</code> <code class="p">=</code> <code class="n">rotate</code><code class="p">(</code><code class="n">sub_square</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">half_sz</code><code class="p">,</code><code class="n">half_sz</code><code class="p">))</code>
<code class="n">upper_right</code><code class="p">.</code><code class="n">zip</code><code class="p">(</code><code class="n">lower_right</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">l</code><code class="p">,</code><code class="n">r</code><code class="o">|</code> <code class="n">l</code> <code class="o">+</code> <code class="n">r</code> <code class="p">}</code> <code class="o">+</code>
<code class="n">upper_left</code><code class="p">.</code><code class="n">zip</code><code class="p">(</code><code class="n">lower_left</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">l</code><code class="p">,</code><code class="n">r</code><code class="o">|</code> <code class="n">l</code> <code class="o">+</code> <code class="n">r</code> <code class="p">}</code>
<code class="k">else</code>
<code class="n">square</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="n">p</code> <code class="n">rotate</code><code class="p">([[</code>1<code class="p">,</code>2<code class="p">,</code>3<code class="p">,</code>4<code class="p">],</code> <code class="p">[</code>5<code class="p">,</code>6<code class="p">,</code>7<code class="p">,</code>8<code class="p">],</code> <code class="p">[</code>9<code class="p">,</code>10<code class="p">,</code>11<code class="p">,</code>12<code class="p">],</code> <code class="p">[</code>13<code class="p">,</code>14<code class="p">,</code>15<code class="p">,</code>16<code class="p">]])</code>
<code class="p">=</code><code class="o">&gt;</code> <code class="p">[[</code>4<code class="p">,</code> 8<code class="p">,</code> 12<code class="p">,</code> 16<code class="p">],</code> <code class="p">[</code>3<code class="p">,</code> 7<code class="p">,</code> 11<code class="p">,</code> 15<code class="p">],</code> <code class="p">[</code>2<code class="p">,</code> 6<code class="p">,</code> 10<code class="p">,</code> 14<code class="p">],</code> <code class="p">[</code>1<code class="p">,</code> 5<code class="p">,</code> 9<code class="p">,</code> 13<code class="p">]]</code>
</pre></div>
</div>
<p>Our challenge is to refactor them. You could change <code>sub_square</code> from a closure to a private method (and in languages like Java, you have to do that in the first place). What else? Is there any common behaviour we can extract from these two methods?</p>
<p>Looking at the two methods, there are no lines of code that are so obviously identical that we could mechanically extract them into a private helper. Automatic refactoring tools fall down given these two methods. And yet, there is a really, really important refactoring that should be performed here.</p>
<h3 section-num="8.1" id="divide-and-conquer"><span class="section-number">8.1 </span>Divide and Conquer</h3>
<p>Both of these methods use the <a href="http://www.cs.berkeley.edu/~vazirani/algorithms/chap2.pdf">Divide and Conquer</a> strategy.</p>
<p>As described, there are two parts to each divide and conquer algorithm. We&#x2019;ll start with conquer: you need a way to decide if the problem is simple enough to solve in a trivial manner, and a trivial solution. You&#x2019;ll also need a way to divide the problem into sub-problems if it&#x2019;s too complex for the trivial solution, and a way to recombine the pieces back into the solution. The entire process is carried our recursively.</p>
<p>For example, here&#x2019;s how <code>#rotate</code> rotated the square. We started with a square matrix of size 4:</p>
<div class="code-block">
<div class="highlight"><pre><code class="p">[</code>
<code class="p">[</code> 1<code class="p">,</code> 2<code class="p">,</code> 3<code class="p">,</code> 4<code class="p">],</code>
<code class="p">[</code> 5<code class="p">,</code> 6<code class="p">,</code> 7<code class="p">,</code> 8<code class="p">],</code>
<code class="p">[</code> 9<code class="p">,</code> 10<code class="p">,</code> 11<code class="p">,</code> 12<code class="p">],</code>
<code class="p">[</code> 13<code class="p">,</code> 14<code class="p">,</code> 15<code class="p">,</code> 16<code class="p">]</code>
<code class="p">]</code>
</pre></div>
</div>
<p>That cannot be rotated trivially, so we divided it into four smaller sub-squares:</p>
<div class="code-block">
<div class="highlight"><pre><code class="p">[</code> <code class="p">[</code>
<code class="p">[</code> 1<code class="p">,</code> 2<code class="p">],</code> <code class="p">[</code> 3<code class="p">,</code> 4<code class="p">],</code>
<code class="p">[</code> 5<code class="p">,</code> 6<code class="p">]</code> <code class="p">[</code> 7<code class="p">,</code> 8<code class="p">]</code>
<code class="p">]</code> <code class="p">]</code>
<code class="p">[</code> <code class="p">[</code>
<code class="p">[</code> 9<code class="p">,</code> 10<code class="p">],</code> <code class="p">[</code> 11<code class="p">,</code> 12<code class="p">],</code>
<code class="p">[</code> 13<code class="p">,</code> 14<code class="p">]</code> <code class="p">[</code> 15<code class="p">,</code> 16<code class="p">]</code>
<code class="p">]</code> <code class="p">]</code>
</pre></div>
</div>
<p>Those couldn&#x2019;t be rotated trivially either, so our algorithm divide each of them into four smaller squares again, giving us sixteen squares of one number each. Those are small enough to rotate trivially (they do not change), so the algorithm could stop subdividing.</p>
<p>We said there was a recombination step. For <code>#rotate</code>, four sub-squares are recombined into one square by moving them counter-clockwise 90 degrees. The sixteen smallest squares were recombined into four sub-squares like this:</p>
<div class="code-block">
<div class="highlight"><pre><code class="p">[</code> <code class="p">[</code>
<code class="p">[</code> 2<code class="p">,</code> 6<code class="p">],</code> <code class="p">[</code> 4<code class="p">,</code> 8<code class="p">],</code>
<code class="p">[</code> 1<code class="p">,</code> 5<code class="p">]</code> <code class="p">[</code> 3<code class="p">,</code> 7<code class="p">]</code>
<code class="p">]</code> <code class="p">]</code>
<code class="p">[</code> <code class="p">[</code>
<code class="p">[</code> 10<code class="p">,</code> 14<code class="p">],</code> <code class="p">[</code> 12<code class="p">,</code> 16<code class="p">],</code>
<code class="p">[</code> 9<code class="p">,</code> 13<code class="p">]</code> <code class="p">[</code> 11<code class="p">,</code> 15<code class="p">]</code>
<code class="p">]</code> <code class="p">]</code>
</pre></div>
</div>
<p>Then those four squares were recombined into the final result like this:</p>
<div class="code-block">
<div class="highlight"><pre><code class="p">[</code> <code class="p">[</code>
<code class="p">[</code> 4<code class="p">,</code> 8<code class="p">],</code> <code class="p">[</code> 12<code class="p">,</code> 16<code class="p">],</code>
<code class="p">[</code> 3<code class="p">,</code> 7<code class="p">]</code> <code class="p">[</code> 11<code class="p">,</code> 15<code class="p">]</code>
<code class="p">]</code> <code class="p">]</code>
<code class="p">[</code> <code class="p">[</code>
<code class="p">[</code> 2<code class="p">,</code> 6<code class="p">],</code> <code class="p">[</code> 10<code class="p">,</code> 14<code class="p">],</code>
<code class="p">[</code> 1<code class="p">,</code> 5<code class="p">]</code> <code class="p">[</code> 9<code class="p">,</code> 13<code class="p">]</code>
<code class="p">]</code>
</pre></div>
</div>
<p>And smooshed (that is the technical term) back together:</p>
<div class="code-block">
<div class="highlight"><pre><code class="p">[</code>
<code class="p">[</code> 4<code class="p">,</code> 8<code class="p">,</code> 12<code class="p">,</code> 16<code class="p">],</code>
<code class="p">[</code> 3<code class="p">,</code> 7<code class="p">,</code> 11<code class="p">,</code> 15<code class="p">],</code>
<code class="p">[</code> 2<code class="p">,</code> 6<code class="p">,</code> 10<code class="p">,</code> 14<code class="p">],</code>
<code class="p">[</code> 1<code class="p">,</code> 5<code class="p">,</code> 9<code class="p">,</code> 13<code class="p">]</code>
<code class="p">]</code>
</pre></div>
</div>
<p>And Voila! There is your rotated square matrix.</p>
<p>Both rotation and summing the squares of a tree combine the four steps of a divide and conquer strategy:</p>
<ol><li>Deciding whether the problem is divisible into smaller pieces or can be solved trivially,</li>
<li>A solution fro the trivial case,</li>
<li>A way to divide a non-trivial problem up,</li>
<li>And a way to piece it back together.</li>
</ol><p>Here are the two methods re-written to highlight the common strategy. First, <code>#sum_squares_2</code>:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">public</code>
<code class="n">def</code> <code class="n">sum_squares_2</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="k">if</code> <code class="n">sum_squares_divisible</code>?<code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">sum_squares_recombine</code><code class="p">(</code>
<code class="n">sum_squares_divide</code><code class="p">(</code><code class="n">value</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">sub_value</code><code class="o">|</code> <code class="n">sum_squares_2</code><code class="p">(</code><code class="n">sub_value</code><code class="p">)</code> <code class="o">\</code>
<code class="p">}</code>
<code class="p">)</code>
<code class="k">else</code>
<code class="n">sum_squares_conquer</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="n">private</code>
<code class="n">def</code> <code class="n">sum_squares_divisible</code>?<code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code>
<code class="k">end</code>
<code class="n">def</code> <code class="n">sum_squares_conquer</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">value</code> <code class="o">**</code> 2
<code class="k">end</code>
<code class="n">def</code> <code class="n">sum_squares_divide</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">value</code>
<code class="k">end</code>
<code class="n">def</code> <code class="n">sum_squares_recombine</code><code class="p">(</code><code class="n">values</code><code class="p">)</code>
<code class="n">values</code><code class="p">.</code><code class="n">inject</code><code class="p">()</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="p">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="p">}</code>
<code class="k">end</code>
</pre></div>
</div>
<p>And <code>#rotate_2</code>:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">public</code>
<code class="n">def</code> <code class="n">rotate_2</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="k">if</code> <code class="n">rotate_divisible</code>?<code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">rotate_recombine</code><code class="p">(</code>
<code class="n">rotate_divide</code><code class="p">(</code><code class="n">value</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">sub_value</code><code class="o">|</code> <code class="n">rotate_2</code><code class="p">(</code><code class="n">sub_value</code><code class="p">)</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">else</code>
<code class="n">rotate_conquer</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="n">private</code>
<code class="n">def</code> <code class="n">rotate_divisible</code>?<code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code> <code class="o">&amp;&amp;</code> <code class="n">value</code><code class="p">.</code><code class="nb">size</code> <code class="o">&gt;</code> 1
<code class="k">end</code>
<code class="n">def</code> <code class="n">rotate_conquer</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">value</code>
<code class="k">end</code>
<code class="n">def</code> <code class="n">rotate_divide</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">half_sz</code> <code class="p">=</code> <code class="n">value</code><code class="p">.</code><code class="nb">size</code> <code class="o">/</code> 2
<code class="n">sub_square</code> <code class="p">=</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">row</code><code class="p">,</code> <code class="n">col</code><code class="o">|</code>
<code class="n">value</code><code class="p">.</code><code class="n">slice</code><code class="p">(</code><code class="n">row</code><code class="p">,</code> <code class="n">half_sz</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">a_row</code><code class="o">|</code> <code class="n">a_row</code><code class="p">.</code><code class="n">slice</code><code class="p">(</code><code class="n">col</code><code class="p">,</code> <code class="n">half_sz</code><code class="p">)</code> <code class="p">}</code>
<code class="k">end</code>
<code class="n">upper_left</code> <code class="p">=</code> <code class="n">sub_square</code><code class="p">.</code><code class="n">call</code><code class="p">(</code>0<code class="p">,</code>0<code class="p">)</code>
<code class="n">lower_left</code> <code class="p">=</code> <code class="n">sub_square</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">half_sz</code><code class="p">,</code>0<code class="p">)</code>
<code class="n">upper_right</code> <code class="p">=</code> <code class="n">sub_square</code><code class="p">.</code><code class="n">call</code><code class="p">(</code>0<code class="p">,</code><code class="n">half_sz</code><code class="p">)</code>
<code class="n">lower_right</code> <code class="p">=</code> <code class="n">sub_square</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">half_sz</code><code class="p">,</code><code class="n">half_sz</code><code class="p">)</code>
<code class="p">[</code><code class="n">upper_left</code><code class="p">,</code> <code class="n">lower_left</code><code class="p">,</code> <code class="n">upper_right</code><code class="p">,</code> <code class="n">lower_right</code><code class="p">]</code>
<code class="k">end</code>
<code class="n">def</code> <code class="n">rotate_recombine</code><code class="p">(</code><code class="n">values</code><code class="p">)</code>
<code class="n">upper_left</code><code class="p">,</code> <code class="n">lower_left</code><code class="p">,</code> <code class="n">upper_right</code><code class="p">,</code> <code class="n">lower_right</code> <code class="p">=</code> <code class="n">values</code>
<code class="n">upper_right</code><code class="p">.</code><code class="n">zip</code><code class="p">(</code><code class="n">lower_right</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">l</code><code class="p">,</code><code class="n">r</code><code class="o">|</code> <code class="n">l</code> <code class="o">+</code> <code class="n">r</code> <code class="p">}</code> <code class="o">+</code>
<code class="n">upper_left</code><code class="p">.</code><code class="n">zip</code><code class="p">(</code><code class="n">lower_left</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">l</code><code class="p">,</code><code class="n">r</code><code class="o">|</code> <code class="n">l</code> <code class="o">+</code> <code class="n">r</code> <code class="p">}</code>
<code class="k">end</code>
</pre></div>
</div>
<p>Now the common code is glaringly obvious. The main challenge in factoring it into a helper is deciding whether you want to represent methods like <code>#rotate_divide</code> as lambdas or want to fool around specifying method names as symbols. Let&#x2019;s go with lambdas for the sake of writing a clear example:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">public</code>
<code class="n">def</code> <code class="n">sum_squares_3</code><code class="p">(</code><code class="n">list</code><code class="p">)</code>
<code class="n">divide_and_conquer</code><code class="p">(</code>
<code class="n">list</code><code class="p">,</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code> <code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">**</code> 2 <code class="p">},</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="p">},</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="p">.</code><code class="n">inject</code><code class="p">()</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="p">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="p">}</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">end</code>
<code class="n">def</code> <code class="n">rotate_3</code><code class="p">(</code><code class="n">square</code><code class="p">)</code>
<code class="n">divide_and_conquer</code><code class="p">(</code>
<code class="n">square</code><code class="p">,</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code> <code class="o">&amp;&amp;</code> <code class="n">value</code><code class="p">.</code><code class="n">siz</code><code class="o">\</code>
<code class="n">e</code> <code class="o">&gt;</code> 1 <code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="p">},</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">square</code><code class="o">|</code>
<code class="n">half_sz</code> <code class="p">=</code> <code class="n">square</code><code class="p">.</code><code class="nb">size</code> <code class="o">/</code> 2
<code class="n">sub_square</code> <code class="p">=</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">row</code><code class="p">,</code> <code class="n">col</code><code class="o">|</code>
<code class="n">square</code><code class="p">.</code><code class="n">slice</code><code class="p">(</code><code class="n">row</code><code class="p">,</code> <code class="n">half_sz</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">a_row</code><code class="o">|</code> <code class="n">a_row</code><code class="p">.</code><code class="n">slice</code><code class="p">(</code><code class="n">col</code><code class="p">,</code> <code class="n">half_sz</code><code class="p">)</code> <code class="p">}</code>
<code class="k">end</code>
<code class="n">upper_left</code> <code class="p">=</code> <code class="n">sub_square</code><code class="p">.</code><code class="n">call</code><code class="p">(</code>0<code class="p">,</code>0<code class="p">)</code>
<code class="n">lower_left</code> <code class="p">=</code> <code class="n">sub_square</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">half_sz</code><code class="p">,</code>0<code class="p">)</code>
<code class="n">upper_right</code> <code class="p">=</code> <code class="n">sub_square</code><code class="p">.</code><code class="n">call</code><code class="p">(</code>0<code class="p">,</code><code class="n">half_sz</code><code class="p">)</code>
<code class="n">lower_right</code> <code class="p">=</code> <code class="n">sub_square</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">half_sz</code><code class="p">,</code><code class="n">half_sz</code><code class="p">)</code>
<code class="p">[</code><code class="n">upper_left</code><code class="p">,</code> <code class="n">lower_left</code><code class="p">,</code> <code class="n">upper_right</code><code class="p">,</code> <code class="n">lower_right</code><code class="p">]</code>
<code class="k">end</code><code class="p">,</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code>
<code class="n">upper_left</code><code class="p">,</code> <code class="n">lower_left</code><code class="p">,</code> <code class="n">upper_right</code><code class="p">,</code> <code class="n">lower_right</code> <code class="p">=</code> <code class="n">list</code>
<code class="n">upper_right</code><code class="p">.</code><code class="n">zip</code><code class="p">(</code><code class="n">lower_right</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">l</code><code class="p">,</code><code class="n">r</code><code class="o">|</code> <code class="n">l</code> <code class="o">+</code> <code class="n">r</code> <code class="p">}</code> <code class="o">+</code>
<code class="n">upper_left</code><code class="p">.</code><code class="n">zip</code><code class="p">(</code><code class="n">lower_left</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">l</code><code class="p">,</code><code class="n">r</code><code class="o">|</code> <code class="n">l</code> <code class="o">+</code> <code class="n">r</code> <code class="p">}</code>
<code class="k">end</code>
<code class="p">)</code>
<code class="k">end</code>
<code class="n">private</code>
<code class="n">def</code> <code class="n">divide_and_conquer</code><code class="p">(</code><code class="n">value</code><code class="p">,</code> <code class="n">steps</code><code class="p">)</code>
<code class="k">if</code> <code class="n">steps</code><code class="p">[:</code><code class="n">divisible</code>?<code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">steps</code><code class="p">[:</code><code class="n">recombine</code><code class="p">].</code><code class="n">call</code><code class="p">(</code>
<code class="n">steps</code><code class="p">[:</code><code class="n">divide</code><code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">sub_value</code><code class="o">|</code> <code class="n">divide_and_conquer</code><code class="p">(</code><code class="n">sub_v</code><code class="o">\</code>
<code class="n">alue</code><code class="p">,</code> <code class="n">steps</code><code class="p">)</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">else</code>
<code class="n">steps</code><code class="p">[:</code><code class="n">conquer</code><code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
</pre></div>
</div>
<p>Now we have refactored the common algorithm out. Typically, something like divide and conquer is treated as a &#x201C;pattern,&#x201D; a recipe for writing methods. We have changed it into an <em>abstraction</em> by writing a <code>#divide_and_conquer</code> method and passing it our own functions which it combines to form the final algorithm. That ought to sound familiar: <code>#divide_and_conquer</code> is a <em>combinator</em> that creates recursive methods for us.</p>
<p>You can also find recursive combinators in other languages like Joy, Factor, and even Javascript (the recursive combinator presented here as <code>#divide_and_conquer</code> is normally called <code>multirec</code>). Eugene Lazutkin&#x2019;s article on [Using recursion combinators in JavaScript](http://lazutkin.com/blog/2008/jun/30/using-recursion-combinators-javascript/ &#x201C;&#x201D;) shows how to use combinators to build divide and conquer algorithms in Javascript with the Dojo libraries. This example uses <code>binrec</code>, a recursive combinator for algorithms that always divide their problems in two:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">var</code> <code class="n">fib0</code> <code class="p">=</code> <code class="k">function</code><code class="p">(</code><code class="n">n</code><code class="p">){</code>
<code class="k">return</code> <code class="n">n</code> <code class="o">&lt;</code><code class="p">=</code> 1 ? 1 <code class="p">:</code>
<code class="n">arguments</code><code class="p">.</code><code class="n">callee</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">this</code><code class="p">,</code> <code class="n">n</code> <code class="o">-</code> 1<code class="p">)</code> <code class="o">+</code>
<code class="n">arguments</code><code class="p">.</code><code class="n">callee</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">this</code><code class="p">,</code> <code class="n">n</code> <code class="o">-</code> 2<code class="p">);</code>
<code class="p">};</code>
<code class="n">var</code> <code class="n">fib1</code> <code class="p">=</code> <code class="n">binrec</code><code class="p">(</code>"<code class="o">&lt;</code><code class="p">=</code> 1"<code class="p">,</code> "1"<code class="p">,</code> "<code class="p">[[</code><code class="n">n</code> <code class="o">-</code> 1<code class="p">],</code> <code class="p">[</code><code class="n">n</code> <code class="o">-</code> 2<code class="p">]]</code>"<code class="p">,</code> "<code class="o">+</code>"<code class="p">);</code>
</pre></div>
</div>
<h3 section-num="8.2" id="the-merge-sort"><span class="section-number">8.2 </span>The Merge Sort</h3>
<p>Let&#x2019;s look at another example, implementing a <a href="http://en.wikipedia.org/wiki/Merge_sort" title="Merge sort - Wikipedia, the free encyclopedia">merge sort</a>. This algorithm has a distinguished pedigree: It was invented by John Von Neumann in 1945. </p>
<blockquote>
<p>Von Neumann was a brilliant and fascinating individual. he is most famous amongst Computer Scientists for formalizing the computer architecture which now bears his name. he also worked on game theory, and it was no game to him: He hoped to use math to advise the United States whether an when to launch a thermonuclear war on the USSR. If you are interested in reading more, <a href="http://www.amazon.com/gp/product/038541580X?ie=UTF8&amp;tag=raganwald001-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=038541580X" title="Amazon.com: Prisoner's Dilemma: William Poundstone: Books">Prisoner&#x2019;s Dilemma</a> is a very fine book about both game theory and one of the great minds of modern times.</p>
</blockquote>
<p>Conceptually, a merge sort works as follows:</p>
<ul><li>If the list is of length 0 or 1, then it is already sorted.</li>
<li>Otherwise:
<ol><li>Divide the unsorted list into two sublists of about half the size.</li>
<li>Sort each sublist recursively by re-applying merge sort.</li>
<li>Merge the two sublists back into one sorted list.</li>
</ol></li>
</ul><p>The merge sort part will be old hat given our <code>#divide_and_conquer</code> helper:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">def</code> <code class="n">merge_sort</code><code class="p">(</code><code class="n">list</code><code class="p">)</code>
<code class="n">divide_and_conquer</code><code class="p">(</code>
<code class="n">list</code><code class="p">,</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="p">.</code><code class="nb">length</code> <code class="o">&gt;</code> 1 <code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code> <code class="p">},</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code>
<code class="n">half_index</code> <code class="p">=</code> <code class="p">(</code><code class="n">list</code><code class="p">.</code><code class="nb">length</code> <code class="o">/</code> 2<code class="p">)</code> <code class="o">-</code> 1
<code class="p">[</code> <code class="n">list</code><code class="p">[</code>0<code class="p">..</code><code class="n">half_index</code><code class="p">],</code> <code class="n">list</code><code class="p">[(</code><code class="n">half_index</code> <code class="o">+</code> 1<code class="p">)..</code><code class="o">-</code>1<code class="p">]</code> <code class="p">]</code>
<code class="k">end</code><code class="p">,</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">pair</code><code class="o">|</code> <code class="n">merge_two_sorted_lists</code><code class="p">(</code><code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">,</code> <code class="n">pair</code><code class="o">.\</code>
<code class="n">last</code><code class="p">)</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">end</code>
</pre></div>
</div>
<p>The interesting part is our <code>#merge_two_sorted_lists</code> method. Given two sorted lists, our merge algorithm works like this:</p>
<ul><li>If either list is of length zero, return the other list.</li>
<li>Otherwise:
<ol><li>Compare the first item of each list using <code>&lt;=&gt;</code>. Let&#x2019;s call the list which has the &#x201C;preceding&#x201D; first item the preceding list and the list which has the &#x201C;following&#x201D; first item the following list.</li>
<li>Create a pair of lists consisting of the preceding item and an empty list, and another pair of lists consisting of the remainder of the preceding list and the entire following list.</li>
<li>Merge each pair of lists recursively by applying merge two sorted lists.</li>
<li>Catenate the results together.</li>
</ol></li>
</ul><p>As you can tell from the description, this is another divide and conquer algorithm:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">def</code> <code class="n">merge_two_sorted_lists</code><code class="p">(</code><code class="o">*</code><code class="n">pair</code><code class="p">)</code>
<code class="n">divide_and_conquer</code><code class="p">(</code>
<code class="n">pair</code><code class="p">,</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">pair</code><code class="o">|</code> !<code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">.</code><code class="n">empty</code>? <code class="o">&amp;&amp;</code> !<code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">.</code><code class="n">empty</code>? <code class="o">\</code>
<code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">pair</code><code class="o">|</code>
<code class="k">if</code> <code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">.</code><code class="n">empty</code>? <code class="o">&amp;&amp;</code> <code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">.</code><code class="n">empty</code>?
<code class="p">[]</code>
<code class="n">elsif</code> <code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">.</code><code class="n">empty</code>?
<code class="n">pair</code><code class="p">.</code><code class="n">last</code>
<code class="k">else</code>
<code class="n">pair</code><code class="p">.</code><code class="n">first</code>
<code class="k">end</code>
<code class="k">end</code><code class="p">,</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">pair</code><code class="o">|</code>
<code class="n">preceding</code><code class="p">,</code> <code class="n">following</code> <code class="p">=</code> <code class="k">case</code> <code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">.</code><code class="n">first</code> <code class="o">&lt;</code><code class="p">=</code><code class="o">&gt;</code> <code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">.</code><code class="n">first</code>
<code class="n">when</code> <code class="o">-</code>1<code class="p">:</code> <code class="p">[</code><code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">,</code> <code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">]</code>
<code class="n">when</code> 0<code class="p">:</code> <code class="p">[</code><code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">,</code> <code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">]</code>
<code class="n">when</code> 1<code class="p">:</code> <code class="p">[</code><code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">,</code> <code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">]</code>
<code class="k">end</code>
<code class="p">[</code>
<code class="p">[[</code><code class="n">preceding</code><code class="p">.</code><code class="n">first</code><code class="p">],</code> <code class="p">[]],</code>
<code class="p">[</code><code class="n">preceding</code><code class="p">[</code>1<code class="p">..</code><code class="o">-</code>1<code class="p">],</code> <code class="n">following</code><code class="p">]</code>
<code class="p">]</code>
<code class="k">end</code><code class="p">,</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">pair</code><code class="o">|</code> <code class="n">pair</code><code class="p">.</code><code class="n">first</code> <code class="o">+</code> <code class="n">pair</code><code class="p">.</code><code class="n">last</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">end</code>
</pre></div>
</div>
<p>That&#x2019;s great. Well, that&#x2019;s barely ok, actually. The problem is that when doing our merge sort, when we decide which item is the preceding item (least most, front most, whatever you want to call it), we already know that it is a trivial item and that it doesn&#x2019;t need any further merging. The only reason we bundle it up in <code>[[preceding.first], []]</code> is because our <code>#divide_and_conquer</code> method expects to recursively attempt to solve all of the sub-problems we generate.</p>
<p>In this case, <code>#merge_two_sorted_lists</code> does not really divide a problem into a list of one or more sub-problems, some of which may or may not be trivially solvable. Instead, it divides a problem into a part of the solution and a single sub-problem which may or may not be trivially solvable. This common strategy also has a name, <a href="http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Recn/Linear/" title="Linear Recursion">linear recursion</a>.</p>
<p>Let&#x2019;s write another version of <code>#merge_two_sorted_lists</code>, but his time instead of using <code>#divide_and_conquer</code>, we&#x2019;ll write a linear recursion combinator:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">def</code> <code class="n">merge_two_sorted_lists</code><code class="p">(</code><code class="o">*</code><code class="n">pair</code><code class="p">)</code>
<code class="n">linear_recursion</code><code class="p">(</code>
<code class="n">pair</code><code class="p">,</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">pair</code><code class="o">|</code> !<code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">.</code><code class="n">empty</code>? <code class="o">&amp;&amp;</code> !<code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">.</code><code class="n">empty</code>? <code class="o">\</code>
<code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">pair</code><code class="o">|</code>
<code class="k">if</code> <code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">.</code><code class="n">empty</code>? <code class="o">&amp;&amp;</code> <code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">.</code><code class="n">empty</code>?
<code class="p">[]</code>
<code class="n">elsif</code> <code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">.</code><code class="n">empty</code>?
<code class="n">pair</code><code class="p">.</code><code class="n">last</code>
<code class="k">else</code>
<code class="n">pair</code><code class="p">.</code><code class="n">first</code>
<code class="k">end</code>
<code class="k">end</code><code class="p">,</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">pair</code><code class="o">|</code>
<code class="n">preceding</code><code class="p">,</code> <code class="n">following</code> <code class="p">=</code> <code class="k">case</code> <code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">.</code><code class="n">first</code> <code class="o">&lt;</code><code class="p">=</code><code class="o">&gt;</code> <code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">.</code><code class="n">first</code>
<code class="n">when</code> <code class="o">-</code>1<code class="p">:</code> <code class="p">[</code><code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">,</code> <code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">]</code>
<code class="n">when</code> 0<code class="p">:</code> <code class="p">[</code><code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">,</code> <code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">]</code>
<code class="n">when</code> 1<code class="p">:</code> <code class="p">[</code><code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">,</code> <code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">]</code>
<code class="k">end</code>
<code class="p">[</code> <code class="n">preceding</code><code class="p">.</code><code class="n">first</code><code class="p">,</code> <code class="p">[</code><code class="n">preceding</code><code class="p">[</code>1<code class="p">..</code><code class="o">-</code>1<code class="p">],</code> <code class="n">following</code><code class="p">]</code> <code class="p">]</code>
<code class="k">end</code><code class="p">,</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">trivial_bit</code><code class="p">,</code> <code class="n">divisible_bit</code><code class="o">|</code> <code class="p">[</code><code class="n">trivial_bit</code><code class="p">]</code> <code class="o">+</code> <code class="n">div</code><code class="o">\</code>
<code class="n">isible_bit</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">end</code>
<code class="n">def</code> <code class="n">linear_recursion</code><code class="p">(</code><code class="n">value</code><code class="p">,</code> <code class="n">steps</code><code class="p">)</code>
<code class="k">if</code> <code class="n">steps</code><code class="p">[:</code><code class="n">divisible</code>?<code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">trivial_part</code><code class="p">,</code> <code class="n">sub_problem</code> <code class="p">=</code> <code class="n">steps</code><code class="p">[:</code><code class="n">divide</code><code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">steps</code><code class="p">[:</code><code class="n">recombine</code><code class="p">].</code><code class="n">call</code><code class="p">(</code>
<code class="n">trivial_part</code><code class="p">,</code> <code class="n">linear_recursion</code><code class="p">(</code><code class="n">sub_problem</code><code class="p">,</code> <code class="n">steps</code><code class="p">)</code>
<code class="p">)</code>
<code class="k">else</code>
<code class="n">steps</code><code class="p">[:</code><code class="n">conquer</code><code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
</pre></div>
</div>
<p>You may think this is even better, and it is.</p>
<h3 section-num="8.3" id="separating-declaration-from-implementation"><span class="section-number">8.3 </span>Separating Declaration from Implementation</h3>
<p>Using recursive combinators like <code>#divide_and_conquer</code> and <code>#linear_recursion</code> are abstraction wins. They make recursive code much easier to read, because you know the general form of the algorithm and don&#x2019;t need to pick through it to discover the individual steps. But there&#x2019;s another benefit we should consider: <em>Recursive combinators separate declaration from implementation.</em></p>
<p>Consider <code>#linear_recursion</code> again. This is <em>not</em> the fastest possible implementation. There is a long and tedious argument that arises when one programmer argues it should be implemented with iteration for performance, and the other argues it should be implemented with recursion for clarity, and a third programmer who never uses recursion claims the iterative solution is easier to understand&#x2026;</p>
<p>Imagine a huge code base full of <code>#linear_recursion</code> and <code>#divide_and_conquer</code> calls. What happens if you decide that each one of these algorithms should be implemented with iteration? Hmmm&#x2026; How about we modify <code>#linear_recursion</code> and <code>#divide_and_conquer</code>, and all of the methods that call them switch from recursion to iteration for free?</p>
<p>Or perhaps we decide that we really should take advantage of multiple threads&#x2026; Do you see where this is going? You can write a new implementation and again, all of the existing methods are upgraded.</p>
<p>Even if you do not plan to change the implementation, let&#x2019;s face a simple fact: when writing a brand new recursive or iterative method, you really have two possible sources of bugs: you may not have declared the solution correctly, and you may not implement it correctly.</p>
<p>Using combinators like <code>#divide_and_conquer</code> simplifies things: You only need to get your declaration of the solution correct, the implementation is taken care of for you. This is a tremendous win when writing recursive functions.</p>
<p>For these reasons, I strongly encourage the use of recursion combinators, either those supplied here or ones you write for yourself.</p>
<h3 section-num="8.4" id="practical-recursive-combinators"><span class="section-number">8.4 </span>Practical Recursive Combinators</h3>
<p>We&#x2019;ve seen how recursive combinators like <code>#divide_and_conquer</code> and <code>#linear_recursion</code> are abstraction wins. They make recursive code much easier to read, because you know the general form of the algorithm and don&#x2019;t need to pick through it to discover the individual steps.</p>
<p>We also saw that by separating the recursion implementation from the declaration of how to perform the steps of an algorithm like <code>#rotate</code>, we leave ourselves the opportunity to improve the performance of our implementation without the risk of adding bugs to our declaration. And today we&#x2019;re going to do just that, along with a few tweaks for usability.</p>
<p>In this section, we&#x2019;re going to optimize our combinators&#x2019; performance and make them a little easier to use with goodies like <code>string_to_proc</code>. To do that, we&#x2019;re going to work with closures, defining methods with <code>define_method</code>, and implement functional programming&#x2019;s partial application. We&#x2019;ll wrap up by converting <code>linrec</code> from a recursive to an iterative implementation.</p>
<p>First, a little organization. Here are the original examples. I&#x2019;ve placed them in a module and named the combinators <code>multirec</code> and <code>linrec</code> in conformance with common practice:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">module</code> <code class="n">RecursiveCombinators</code>
<code class="n">def</code> <code class="n">multirec</code><code class="p">(</code><code class="n">value</code><code class="p">,</code> <code class="n">steps</code><code class="p">)</code>
<code class="k">if</code> <code class="n">steps</code><code class="p">[:</code><code class="n">divisible</code>?<code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">steps</code><code class="p">[:</code><code class="n">recombine</code><code class="p">].</code><code class="n">call</code><code class="p">(</code>
<code class="n">steps</code><code class="p">[:</code><code class="n">divide</code><code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">sub_value</code><code class="o">|</code> <code class="n">multirec</code><code class="p">(</code><code class="n">sub_value</code><code class="p">,</code> <code class="n">st</code><code class="o">\</code>
<code class="nb">eps</code><code class="p">)</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">else</code>
<code class="n">steps</code><code class="p">[:</code><code class="n">conquer</code><code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="n">def</code> <code class="n">linrec</code><code class="p">(</code><code class="n">value</code><code class="p">,</code> <code class="n">steps</code><code class="p">)</code>
<code class="k">if</code> <code class="n">steps</code><code class="p">[:</code><code class="n">divisible</code>?<code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">trivial_part</code><code class="p">,</code> <code class="n">sub_problem</code> <code class="p">=</code> <code class="n">steps</code><code class="p">[:</code><code class="n">divide</code><code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">steps</code><code class="p">[:</code><code class="n">recombine</code><code class="p">].</code><code class="n">call</code><code class="p">(</code>
<code class="n">trivial_part</code><code class="p">,</code> <code class="n">linrec</code><code class="p">(</code><code class="n">sub_problem</code><code class="p">,</code> <code class="n">steps</code><code class="p">)</code>
<code class="p">)</code>
<code class="k">else</code>
<code class="n">steps</code><code class="p">[:</code><code class="n">conquer</code><code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="n">module_function</code> <code class="p">:</code><code class="n">multirec</code><code class="p">,</code> <code class="p">:</code><code class="n">linrec</code>
<code class="k">end</code>
</pre></div>
</div>
<p>Since they are also module functions, call them by sending a message to the module:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">def</code> <code class="n">merge_sort</code><code class="p">(</code><code class="n">list</code><code class="p">)</code>
<code class="n">RecursiveCombinators</code><code class="p">.</code><code class="n">multirec</code><code class="p">(</code>
<code class="n">list</code><code class="p">,</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="p">.</code><code class="nb">length</code> <code class="o">&gt;</code> 1 <code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code> <code class="p">},</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code>
<code class="n">half_index</code> <code class="p">=</code> <code class="p">(</code><code class="n">list</code><code class="p">.</code><code class="nb">length</code> <code class="o">/</code> 2<code class="p">)</code> <code class="o">-</code> 1
<code class="p">[</code> <code class="n">list</code><code class="p">[</code>0<code class="p">..</code><code class="n">half_index</code><code class="p">],</code> <code class="n">list</code><code class="p">[(</code><code class="n">half_index</code> <code class="o">+</code> 1<code class="p">)..</code><code class="o">-</code>1<code class="p">]</code> <code class="p">]</code>
<code class="k">end</code><code class="p">,</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">pair</code><code class="o">|</code> <code class="n">merge_two_sorted_lists</code><code class="p">(</code><code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">,</code> <code class="n">pair</code><code class="o">.\</code>
<code class="n">last</code><code class="p">)</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">end</code>
</pre></div>
</div>
<p>Or you can include the <code>RecursiveCombinators</code> module and call either method directly:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">include</code> <code class="n">RecursiveCombinators</code>
<code class="n">def</code> <code class="n">merge_two_sorted_lists</code><code class="p">(</code><code class="o">*</code><code class="n">pair</code><code class="p">)</code>
<code class="n">linrec</code><code class="p">(</code>
<code class="n">pair</code><code class="p">,</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">pair</code><code class="o">|</code> !<code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">.</code><code class="n">empty</code>? <code class="o">&amp;&amp;</code> !<code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">.</code><code class="n">empty</code>? <code class="o">\</code>
<code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">pair</code><code class="o">|</code>
<code class="k">if</code> <code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">.</code><code class="n">empty</code>? <code class="o">&amp;&amp;</code> <code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">.</code><code class="n">empty</code>?
<code class="p">[]</code>
<code class="n">elsif</code> <code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">.</code><code class="n">empty</code>?
<code class="n">pair</code><code class="p">.</code><code class="n">last</code>
<code class="k">else</code>
<code class="n">pair</code><code class="p">.</code><code class="n">first</code>
<code class="k">end</code>
<code class="k">end</code><code class="p">,</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">pair</code><code class="o">|</code>
<code class="n">preceding</code><code class="p">,</code> <code class="n">following</code> <code class="p">=</code> <code class="k">case</code> <code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">.</code><code class="n">first</code> <code class="o">&lt;</code><code class="p">=</code><code class="o">&gt;</code> <code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">.</code><code class="n">first</code>
<code class="n">when</code> <code class="o">-</code>1<code class="p">:</code> <code class="p">[</code><code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">,</code> <code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">]</code>
<code class="n">when</code> 0<code class="p">:</code> <code class="p">[</code><code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">,</code> <code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">]</code>
<code class="n">when</code> 1<code class="p">:</code> <code class="p">[</code><code class="n">pair</code><code class="p">.</code><code class="n">last</code><code class="p">,</code> <code class="n">pair</code><code class="p">.</code><code class="n">first</code><code class="p">]</code>
<code class="k">end</code>
<code class="p">[</code> <code class="n">preceding</code><code class="p">.</code><code class="n">first</code><code class="p">,</code> <code class="p">[</code><code class="n">preceding</code><code class="p">[</code>1<code class="p">..</code><code class="o">-</code>1<code class="p">],</code> <code class="n">following</code><code class="p">]</code> <code class="p">]</code>
<code class="k">end</code><code class="p">,</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">trivial_bit</code><code class="p">,</code> <code class="n">divisible_bit</code><code class="o">|</code> <code class="p">[</code><code class="n">trivial_bit</code><code class="p">]</code> <code class="o">+</code> <code class="n">div</code><code class="o">\</code>
<code class="n">isible_bit</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">end</code>
<code class="n">merge_sort</code><code class="p">([</code>8<code class="p">,</code> 3<code class="p">,</code> 10<code class="p">,</code> 1<code class="p">,</code> 9<code class="p">,</code> 5<code class="p">,</code> 7<code class="p">,</code> 4<code class="p">,</code> 6<code class="p">,</code> 2<code class="p">])</code>
<code class="p">=</code><code class="o">&gt;</code> <code class="p">[</code>1<code class="p">,</code> 2<code class="p">,</code> 3<code class="p">,</code> 4<code class="p">,</code> 5<code class="p">,</code> 6<code class="p">,</code> 7<code class="p">,</code> 8<code class="p">,</code> 9<code class="p">,</code> 10<code class="p">]</code>
</pre></div>
</div>
<p>Ok, we&#x2019;re ready for some slightly more substantial work. These methods were fine for illustration, but I have a few questions for the author(!)</p>
<h3 section-num="8.5" id="spicing-things-up"><span class="section-number">8.5 </span>Spicing things up</h3>
<p>First, note that every single time we call a method like <code>merge_sort</code>, we create four new lambdas from scratch. This seems wasteful, especially since the lambdas never change. Why create some objects just to throw them away?</p>
<p>On the other hand, it&#x2019;s nice to be able to use create algorithms without having to define a method by name. Although I probably wouldn&#x2019;t do a merge sort anonymously, when I need a one-off quickie, I might like to write something like:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">RecursiveCombinators</code><code class="p">.</code><code class="n">multirec</code><code class="p">(</code>
<code class="p">[</code>1<code class="p">,</code> 2<code class="p">,</code> 3<code class="p">,</code> <code class="p">[[</code>4<code class="p">,</code>5<code class="p">],</code> 6<code class="p">],</code> <code class="p">[[[</code>7<code class="p">]]]],</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code> <code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">**</code> 2 <code class="p">},</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="p">},</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="p">.</code><code class="n">inject</code><code class="p">()</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="p">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="p">}</code> <code class="p">}</code>
<code class="p">)</code>
<code class="p">=</code><code class="o">&gt;</code> 140
</pre></div>
</div>
<p>But when I want a permanent sum of the squares method, I <strong>don&#x2019;t</strong> want to write:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">def</code> <code class="n">sum_squares</code><code class="p">(</code><code class="n">list</code><code class="p">)</code>
<code class="n">RecursiveCombinators</code><code class="p">.</code><code class="n">multirec</code><code class="p">(</code>
<code class="n">list</code><code class="p">,</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code> <code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">**</code> 2 <code class="p">},</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="p">},</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="p">.</code><code class="n">inject</code><code class="p">()</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="p">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="p">}</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">end</code>
</pre></div>
</div>
<p>&#x2026;because that would create four lambdas every time I call the function. There are a couple of ways around this problem. First, our &#x201C;recipe&#x201D; for summing squares is a simple hash. We could extract that from the method into a constant:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">SUM_SQUARES_RECIPE</code> <code class="p">=</code> <code class="p">{</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code> <code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">**</code> 2 <code class="p">},</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="p">},</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="p">.</code><code class="n">inject</code><code class="p">()</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="p">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="p">}</code> <code class="p">}</code>
<code class="p">}</code>
<code class="n">def</code> <code class="n">sum_squares</code><code class="p">(</code><code class="n">list</code><code class="p">)</code>
<code class="n">RecursiveCombinators</code><code class="p">.</code><code class="n">multirec</code><code class="p">(</code><code class="n">list</code><code class="p">,</code> <code class="n">SUM_SQUARES_RECIPE</code><code class="p">)</code>
<code class="k">end</code>
</pre></div>
</div>
<p>That (and the isomorphic solution where the constant <code>SUM_SQUARES_RECIPE</code> is instead a private helper method <code>#sum_squares_recipe</code>) is nice if you have some reason you wish to re-use the recipe elsewhere. But we don&#x2019;t, so this merely clutters our class up and separates the method definition from its logic.</p>
<p>I have something in mind. To see what it is, let&#x2019;s start by transforming our method definition from using the <code>def</code> keyword to using the <code>define_method</code> private class method. This obviously needs a module or class to work:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">class</code> <code class="n">Practicum</code>
<code class="n">include</code> <code class="n">RecursiveCombinators</code>
<code class="n">define_method</code> <code class="p">:</code><code class="n">sum_squares</code> <code class="n">do</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code>
<code class="n">multirec</code><code class="p">(</code>
<code class="n">list</code><code class="p">,</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code> <code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">**</code> 2 <code class="p">},</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="p">},</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="p">.</code><code class="n">inject</code><code class="p">()</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="p">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="p">}</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="n">Practicum</code><code class="p">.</code><code class="n">new</code><code class="p">.</code><code class="n">sum_squares</code><code class="p">([</code>1<code class="p">,</code> 2<code class="p">,</code> 3<code class="p">,</code> <code class="p">[[</code>4<code class="p">,</code>5<code class="p">],</code> 6<code class="p">],</code> <code class="p">[[[</code>7<code class="p">]]]])</code>
</pre></div>
</div>
<p>As you probably know, any method taking a block can take a lambda using the <code>&amp;</code> operator, so:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">define_method</code> <code class="o">:</code><code class="n">sum_squares</code><code class="o">,</code> <code class="o">&amp;(</code><code class="n">lambda</code> <code class="k">do</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code>
<code class="n">multirec</code><code class="o">(</code>
<code class="n">list</code><code class="o">,</code>
<code class="o">:</code><code class="n">divisible</code><code class="o">?</code> <code class="o">=&gt;</code> <code class="n">lambda</code> <code class="o">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="o">.</code><code class="na">kind_of</code><code class="o">?(</code><code class="n">Enumerable</code><code class="o">)</code> <code class="o">},</code>
<code class="o">:</code><code class="n">conquer</code> <code class="o">=&gt;</code> <code class="n">lambda</code> <code class="o">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">**</code> <code class="mi">2</code> <code class="o">},</code>
<code class="o">:</code><code class="n">divide</code> <code class="o">=&gt;</code> <code class="n">lambda</code> <code class="o">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">},</code>
<code class="o">:</code><code class="n">recombine</code> <code class="o">=&gt;</code> <code class="n">lambda</code> <code class="o">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="o">.</code><code class="na">inject</code><code class="o">()</code> <code class="o">{</code> <code class="o">|</code><code class="n">x</code><code class="o">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="o">}</code> <code class="o">}</code>
<code class="o">)</code>
<code class="n">end</code><code class="o">)</code>
</pre></div>
</div>
<p>This is useful, because now we can express what we want: a lambda taking one argument that in turn calls <code>multirec</code> with the other arguments filled in. Functional programmers call this <a href="http://ejohn.org/blog/partial-functions-in-javascript/" title="Partial Application in JavaScript">Partial Application</a>. The idea is that if you have a function or method taking two arguments, if you only give it one argument you get a function back that takes the other. So:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">multirec</code><code class="p">(</code><code class="n">x</code><code class="p">).</code><code class="n">call</code><code class="p">(</code><code class="n">y</code><code class="p">)</code>
<code class="p">=</code><code class="o">&gt;</code> <code class="n">multirec</code><code class="p">(</code><code class="n">x</code><code class="p">,</code><code class="n">y</code><code class="p">)</code>
</pre></div>
</div>
<p>Now the drawback with this &#x201C;standard&#x201D; implementation of partial application is that we would pass a list to <code>multirec</code> and get back a function taking a hash of declarations. That isn&#x2019;t what we want. We could partially apply things <em>backwards</em> so that <code>multirec(x).call(y) =&gt; multirec(y,x)</code> (if Ruby was a concatenative language, we would be concatenating the multirec combinator with a thrush). The trouble with that is it is the reverse of how partial application works in every other <a href="http://www.haskell.org/" title="HaskellWiki">programming language</a> and <a href="https://github.com/osteele/functional-javascript/tree">functional programming library</a>.</p>
<p>Instead, we will switch the arguments to <code>multirec</code> ourselves, so it now works like this:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">multirec</code><code class="p">(</code>
<code class="p">{</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code> <code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">**</code> 2 <code class="p">},</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="p">},</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="p">.</code><code class="n">inject</code><code class="p">()</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="p">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="p">}</code> <code class="p">}</code>
<code class="p">},</code>
<code class="n">list</code>
<code class="p">)</code>
</pre></div>
</div>
<p>The drawback with this approach is that we lose a little of Ruby&#x2019;s syntactic sugar, the ability to fake named parameters by passing hash arguments without <code>{}</code> if they are the last parameter. And now, let&#x2019;s give it the ability to partially apply itself. You can do some stuff with allowing multiple arguments and counting the number of arguments, but we&#x2019;re going to make the wild assumption that you never attempt a recursive combinator on <code>nil</code>. Here&#x2019;s <code>multirec</code>, you can infer the implementation for <code>linrec</code>:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">def</code> <code class="n">multirec</code><code class="p">(</code><code class="n">steps</code><code class="p">,</code> <code class="n">optional_value</code> <code class="p">=</code> <code class="n">nil</code><code class="p">)</code>
<code class="n">worker_proc</code> <code class="p">=</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code>
<code class="k">if</code> <code class="n">steps</code><code class="p">[:</code><code class="n">divisible</code>?<code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">steps</code><code class="p">[:</code><code class="n">recombine</code><code class="p">].</code><code class="n">call</code><code class="p">(</code>
<code class="n">steps</code><code class="p">[:</code><code class="n">divide</code><code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">).</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">sub_value</code><code class="o">|</code> <code class="n">worker_proc</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">sub_v</code><code class="o">\</code>
<code class="n">alue</code><code class="p">)</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">else</code>
<code class="n">steps</code><code class="p">[:</code><code class="n">conquer</code><code class="p">].</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">if</code> <code class="n">optional_value</code><code class="p">.</code><code class="n">nil</code>?
<code class="n">worker_proc</code>
<code class="k">else</code>
<code class="n">worker_proc</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">optional_value</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
</pre></div>
</div>
<p>Notice that you get the same correct result whether you write:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">RecursiveCombinators</code><code class="p">.</code><code class="n">multirec</code><code class="p">(</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code> <code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">**</code> 2 <code class="p">},</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="p">},</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="p">.</code><code class="n">inject</code><code class="p">()</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="p">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="p">}</code> <code class="p">}</code>
<code class="p">).</code><code class="n">call</code><code class="p">([</code>1<code class="p">,</code> 2<code class="p">,</code> 3<code class="p">,</code> <code class="p">[[</code>4<code class="p">,</code>5<code class="p">],</code> 6<code class="p">],</code> <code class="p">[[[</code>7<code class="p">]]]])</code>
<code class="p">=</code><code class="o">&gt;</code> 140
</pre></div>
</div>
<p>Or:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">RecursiveCombinators</code><code class="p">.</code><code class="n">multirec</code><code class="p">(</code>
<code class="p">{</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code> <code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">**</code> 2 <code class="p">},</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="p">},</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="p">.</code><code class="n">inject</code><code class="p">()</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="p">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="p">}</code> <code class="p">}</code>
<code class="p">},</code>
<code class="p">[</code>1<code class="p">,</code> 2<code class="p">,</code> 3<code class="p">,</code> <code class="p">[[</code>4<code class="p">,</code>5<code class="p">],</code> 6<code class="p">],</code> <code class="p">[[[</code>7<code class="p">]]]]</code>
<code class="p">)</code>
<code class="p">=</code><code class="o">&gt;</code> 140
</pre></div>
</div>
<p>Let&#x2019;s go back to what we were trying to do with <code>&amp;</code>:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">define_method</code> <code class="o">:</code><code class="n">sum_squares</code><code class="o">,</code> <code class="o">&amp;(</code><code class="n">lambda</code> <code class="k">do</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code>
<code class="n">multirec</code><code class="o">(</code>
<code class="n">list</code><code class="o">,</code>
<code class="o">:</code><code class="n">divisible</code><code class="o">?</code> <code class="o">=&gt;</code> <code class="n">lambda</code> <code class="o">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="o">.</code><code class="na">kind_of</code><code class="o">?(</code><code class="n">Enumerable</code><code class="o">)</code> <code class="o">},</code>
<code class="o">:</code><code class="n">conquer</code> <code class="o">=&gt;</code> <code class="n">lambda</code> <code class="o">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">**</code> <code class="mi">2</code> <code class="o">},</code>
<code class="o">:</code><code class="n">divide</code> <code class="o">=&gt;</code> <code class="n">lambda</code> <code class="o">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">},</code>
<code class="o">:</code><code class="n">recombine</code> <code class="o">=&gt;</code> <code class="n">lambda</code> <code class="o">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="o">.</code><code class="na">inject</code><code class="o">()</code> <code class="o">{</code> <code class="o">|</code><code class="n">x</code><code class="o">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="o">}</code> <code class="o">}</code>
<code class="o">)</code>
<code class="n">end</code><code class="o">)</code>
</pre></div>
</div>
<p>Now we know how to build our lambda:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">require</code> <code class="s">'partial_application_recursive_combinators'</code>
<code class="n">class</code> <code class="n">Practicum</code>
<code class="n">extend</code> <code class="n">PartialApplicationRecursiveCombinators</code> # <code class="n">so</code> <code class="n">we</code> <code class="n">can</code> <code class="n">call</code> <code class="n">multirec</code><code class="o">\</code>
<code class="n">in</code> <code class="n">class</code> <code class="n">scope</code>
<code class="n">define_method</code> <code class="p">:</code><code class="n">sum_squares</code><code class="p">,</code> <code class="o">&amp;</code><code class="n">multirec</code><code class="p">(</code>
<code class="p">:</code><code class="n">divisible</code>? <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Enumerable</code><code class="p">)</code> <code class="p">},</code>
<code class="p">:</code><code class="n">conquer</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">**</code> 2 <code class="p">},</code>
<code class="p">:</code><code class="n">divide</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="p">},</code>
<code class="p">:</code><code class="n">recombine</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="p">.</code><code class="n">inject</code><code class="p">()</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="p">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="p">}</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">end</code>
<code class="n">Practicum</code><code class="p">.</code><code class="n">new</code><code class="p">.</code><code class="n">sum_squares</code><code class="p">([</code>1<code class="p">,</code> 2<code class="p">,</code> 3<code class="p">,</code> <code class="p">[[</code>4<code class="p">,</code>5<code class="p">],</code> 6<code class="p">],</code> <code class="p">[[[</code>7<code class="p">]]]])</code>
<code class="p">=</code><code class="o">&gt;</code> 140
</pre></div>
</div>
<p>You can verify for yourself that no matter how many times you call <code>sum_squares</code>, you do not build those lambdas again. What we have just done is added partial application to <code>multirec</code> and <code>linrec</code>, which in turn allows us to ensure that he cost of constructing lambdas for our methods is only done when the method is defined, not every time it is called.</p>
<h3 section-num="8.6" id="building-on-a-legacy"><span class="section-number">8.6 </span>Building on a legacy</h3>
<p>We have already renamed <code>divide_and_conquer</code> and <code>linear_recursion</code> to bring them into line with standard practice and other programming languages. Now it&#x2019;s time for us to bring the parameters&#x2013;the declarative lambdas&#x2013;into line with standard practice.</p>
<p>The four arguments to both methods are normally called <code>cond</code>, <code>then</code>, <code>before</code>, and <code>after</code>:</p>
<ul><li><code>cond</code> is the logical inverse of <code>divisible?</code> So if <code>cond(value)</code> evaluates to true, then we do not need to subdivide the problem.</li>
<li><code>then</code> is exactly the same as <code>conquer</code>, <em>if</em> cond <em>then</em> then. That&#x2019;s the way I think of it.</li>
<li><code>before</code> is the same as <code>divide</code>.</li>
<li><code>after</code> is the same as <code>recombine</code>.</li>
</ul><p>Things look very similar with the new scheme for now:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">require</code> <code class="s">'legacy_recursive_combinators'</code>
<code class="n">class</code> <code class="n">Practicum</code>
<code class="n">extend</code> <code class="n">LegacyRecursiveCombinators</code> # <code class="n">so</code> <code class="n">we</code> <code class="n">can</code> <code class="n">call</code> <code class="n">multirec</code> <code class="n">in</code> <code class="n">class</code> <code class="n">sc</code><code class="o">\</code>
<code class="n">ope</code>
<code class="n">define_method</code> <code class="p">:</code><code class="n">sum_squares</code><code class="p">,</code> <code class="o">&amp;</code><code class="n">multirec</code><code class="p">(</code>
<code class="p">:</code><code class="n">cond</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="p">.</code><code class="n">kind_of</code>?<code class="p">(</code><code class="n">Numeric</code><code class="p">)</code> <code class="p">},</code> # <code class="n">the</code> <code class="n">only</code> <code class="n">change</code><code class="o">\</code>
<code class="n">right</code> <code class="n">now</code>
<code class="p">:</code><code class="n">then</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">**</code> 2 <code class="p">},</code>
<code class="p">:</code><code class="n">before</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="p">},</code>
<code class="p">:</code><code class="n">after</code> <code class="p">=</code><code class="o">&gt;</code> <code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="p">.</code><code class="n">inject</code><code class="p">()</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="p">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="p">}</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">end</code>
</pre></div>
</div>
<p>All right, now our combinators will look familiar to functional programmers, and even better when we look at functional programs using recursive combinators we will understand them at a glance. Okay, let&#x2019;s get serious and work on making our combinators easy to use and our code easy to read.</p>
<h3 section-num="8.7" id="seriously"><span class="section-number">8.7 </span>Seriously</h3>
<p>As long as you&#x2019;re writing these lambdas out, writing <code>:cond =&gt;</code> isn&#x2019;t a hardship. And in an explanatory article like this, it can help at first. However, what if you find a way to abbreviate things? For example, you might <a href="http://github.com/gilesbowkett/archaeopteryx/tree/master" title="gilesbowkett's archaeopteryx">alias <code>lambda</code> to <code>L</code></a>. Or you might want to use <code>string\_to\_proc</code>:</p>
<div class="code-block">
<p class="codeblock-title">string_to_proc.rb</p>
<hr /><div class="highlight"><pre><code class="k">class</code> <code class="nc">String</code>
<code class="k">unless</code> <code class="s1">''</code><code class="o">.</code><code class="n">respond_to?</code><code class="p">(</code><code class="ss">:to_proc</code><code class="p">)</code>
<code class="k">def</code> <code class="nf">to_proc</code> <code class="o">&amp;</code><code class="n">block</code>
<code class="n">params</code> <code class="o">=</code> <code class="o">[]</code>
<code class="n">expr</code> <code class="o">=</code> <code class="nb">self</code>
<code class="n">sections</code> <code class="o">=</code> <code class="n">expr</code><code class="o">.</code><code class="n">split</code><code class="p">(</code><code class="sr">/\s*-&gt;\s*/m</code><code class="p">)</code>
<code class="k">if</code> <code class="n">sections</code><code class="o">.</code><code class="n">length</code> <code class="o">&gt;</code> <code class="mi">1</code> <code class="k">then</code>
<code class="nb">eval</code> <code class="n">sections</code><code class="o">.</code><code class="n">reverse!</code><code class="o">.</code><code class="n">inject</code> <code class="p">{</code> <code class="o">|</code><code class="n">e</code><code class="p">,</code> <code class="nb">p</code><code class="o">|</code> <code class="s2">"(Proc.new { |</code><code class="si">#{</code><code class="nb">p</code><code class="o">.</code><code class="n">split</code><code class="p">(</code><code class="sr">/\\</code>
<code class="sr">s/</code><code class="p">)</code><code class="o">.</code><code class="n">join</code><code class="p">(</code><code class="s1">', '</code><code class="p">)</code><code class="si">}</code><code class="s2">| </code><code class="si">#{</code><code class="n">e</code><code class="si">}</code><code class="s2"> })"</code> <code class="p">},</code> <code class="n">block</code> <code class="o">&amp;&amp;</code> <code class="n">block</code><code class="o">.</code><code class="n">binding</code>
<code class="k">elsif</code> <code class="n">expr</code><code class="o">.</code><code class="n">match</code><code class="p">(</code><code class="sr">/\b_\b/</code><code class="p">)</code>
<code class="nb">eval</code> <code class="s2">"Proc.new { |_| </code><code class="si">#{</code><code class="n">expr</code><code class="si">}</code><code class="s2"> }"</code><code class="p">,</code> <code class="n">block</code> <code class="o">&amp;&amp;</code> <code class="n">block</code><code class="o">.</code><code class="n">binding</code>
<code class="k">else</code>
<code class="n">leftSection</code> <code class="o">=</code> <code class="n">expr</code><code class="o">.</code><code class="n">match</code><code class="p">(</code><code class="sr">/^\s*(?:[+*\/%&amp;|\^\.=&lt;&gt;\[]|!=)/m</code><code class="p">)</code>
<code class="n">rightSection</code> <code class="o">=</code> <code class="n">expr</code><code class="o">.</code><code class="n">match</code><code class="p">(</code><code class="sr">/[+\-*\/%&amp;|\^\.=&lt;&gt;!]\s*$/m</code><code class="p">)</code>
<code class="k">if</code> <code class="n">leftSection</code> <code class="o">||</code> <code class="n">rightSection</code> <code class="k">then</code>
<code class="k">if</code> <code class="p">(</code><code class="n">leftSection</code><code class="p">)</code> <code class="k">then</code>
<code class="n">params</code><code class="o">.</code><code class="n">push</code><code class="p">(</code><code class="s1">'$left'</code><code class="p">)</code>
<code class="n">expr</code> <code class="o">=</code> <code class="s1">'$left'</code> <code class="o">+</code> <code class="n">expr</code>
<code class="k">end</code>
<code class="k">if</code> <code class="p">(</code><code class="n">rightSection</code><code class="p">)</code> <code class="k">then</code>
<code class="n">params</code><code class="o">.</code><code class="n">push</code><code class="p">(</code><code class="s1">'$right'</code><code class="p">)</code>
<code class="n">expr</code> <code class="o">=</code> <code class="n">expr</code> <code class="o">+</code> <code class="s1">'$right'</code>
<code class="k">end</code>
<code class="k">else</code>
<code class="nb">self</code><code class="o">.</code><code class="n">gsub</code><code class="p">(</code>
<code class="sr">/(?:\b[A-Z]|\.[a-zA-Z_$])[a-zA-Z_$\d]*|[a-zA-Z_$][a-zA-Z_\</code>
<code class="sr">$\d]*:|self|arguments|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/</code><code class="p">,</code> <code class="s1">''</code>
<code class="p">)</code><code class="o">.</code><code class="n">scan</code><code class="p">(</code>
<code class="sr">/([a-z_$][a-z_$\d]*)/i</code>
<code class="p">)</code> <code class="k">do</code> <code class="o">|</code><code class="n">v</code><code class="o">|</code>
<code class="n">params</code><code class="o">.</code><code class="n">push</code><code class="p">(</code><code class="n">v</code><code class="p">)</code> <code class="k">unless</code> <code class="n">params</code><code class="o">.</code><code class="n">include?</code><code class="p">(</code><code class="n">v</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="nb">eval</code> <code class="s2">"Proc.new { |</code><code class="si">#{</code><code class="n">params</code><code class="o">.</code><code class="n">join</code><code class="p">(</code><code class="s1">', '</code><code class="p">)</code><code class="si">}</code><code class="s2">| </code><code class="si">#{</code><code class="n">expr</code><code class="si">}</code><code class="s2"> }"</code><code class="p">,</code> <code class="n">block</code> <code class="o">&amp;&amp;</code> <code class="n">bloc</code><code class="p">\</code>
<code class="n">k</code><code class="o">.</code><code class="n">binding</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
</pre></div>
<hr /></div>
<p>So we should support passing the declarative arguments by position as well as by &#x2018;name.&#x2019; And with a final twist, if any of the declarative arguments aren&#x2019;t already lambdas, we&#x2019;ll try to create lambdas by sending them the message <code>to_proc</code>. So our goal is to write what we wrote above or either of the following and have it &#x201C;just work:&#x201D;</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">define_method</code> <code class="o">:</code><code class="n">sum_squares</code><code class="o">,</code> <code class="o">&amp;</code><code class="n">multirec</code><code class="o">(</code>
<code class="n">lambda</code> <code class="o">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code><code class="o">.</code><code class="na">kind_of</code><code class="o">?(</code><code class="n">Numeric</code><code class="o">)</code> <code class="o">},</code> <code class="err">#</code> <code class="n">the</code> <code class="n">only</code> <code class="n">change</code> <code class="n">right</code> <code class="n">now</code>
<code class="n">lambda</code> <code class="o">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">**</code> <code class="mi">2</code> <code class="o">},</code>
<code class="n">lambda</code> <code class="o">{</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code> <code class="n">value</code> <code class="o">},</code>
<code class="n">lambda</code> <code class="o">{</code> <code class="o">|</code><code class="n">list</code><code class="o">|</code> <code class="n">list</code><code class="o">.</code><code class="na">inject</code><code class="o">()</code> <code class="o">{</code> <code class="o">|</code><code class="n">x</code><code class="o">,</code><code class="n">y</code><code class="o">|</code> <code class="n">x</code> <code class="o">+</code> <code class="n">y</code> <code class="o">}</code> <code class="o">}</code>
<code class="o">)</code>
<code class="k">include</code> <code class="s1">'string-to_proc'</code>
<code class="n">define_method</code> <code class="o">:</code><code class="n">sum_squares</code><code class="o">,</code> <code class="o">&amp;</code><code class="n">multirec</code><code class="o">(</code><code class="s2">"value.kind_of?(Numeric)"</code><code class="o">,</code> <code class="s2">"value ** \</code>
<code class="s2">2"</code><code class="o">,</code><code class="s2">"value"</code><code class="o">,</code><code class="s2">"value.inject(&amp;'+')"</code><code class="o">)</code>
</pre></div>
</div>
<p>And here is the code that makes it work:</p>
<div class="code-block">
<p class="codeblock-title">recursive_combinators.rb</p>
<hr /><div class="highlight"><pre><code class="k">module</code> <code class="nn">RecursiveCombinators</code>
<code class="n">separate_args</code> <code class="o">=</code> <code class="nb">lambda</code> <code class="k">do</code> <code class="o">|</code><code class="n">args</code><code class="o">|</code>
<code class="k">if</code> <code class="o">![</code><code class="mi">1</code><code class="p">,</code><code class="mi">2</code><code class="p">,</code><code class="mi">4</code><code class="p">,</code><code class="mi">5</code><code class="o">].</code><code class="n">include?</code><code class="p">(</code><code class="n">args</code><code class="o">.</code><code class="n">length</code><code class="p">)</code>
<code class="k">raise</code> <code class="no">ArgumentError</code>
<code class="k">elsif</code> <code class="n">args</code><code class="o">.</code><code class="n">length</code> <code class="o">&lt;=</code> <code class="mi">2</code>
<code class="n">steps</code> <code class="o">=</code> <code class="o">[</code><code class="ss">:cond</code><code class="p">,</code> <code class="ss">:then</code><code class="p">,</code> <code class="ss">:before</code><code class="p">,</code> <code class="ss">:after</code><code class="o">].</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">k</code><code class="o">|</code> <code class="n">args</code><code class="o">.</code><code class="n">first</code><code class="o">[</code><code class="n">k</code><code class="o">].</code><code class="n">to_pr</code><code class="p">\</code>
<code class="n">oc</code> <code class="p">}</code>
<code class="n">steps</code><code class="o">.</code><code class="n">push</code><code class="p">(</code><code class="n">args</code><code class="o">[</code><code class="mi">1</code><code class="o">]</code><code class="p">)</code> <code class="k">unless</code> <code class="n">args</code><code class="o">[</code><code class="mi">1</code><code class="o">].</code><code class="n">nil?</code>
<code class="n">steps</code>
<code class="k">else</code>
<code class="n">steps</code> <code class="o">=</code> <code class="n">args</code><code class="o">[</code><code class="mi">0</code><code class="o">.</code><code class="n">.</code><code class="mi">3</code><code class="o">].</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">arg</code><code class="o">|</code> <code class="n">arg</code><code class="o">.</code><code class="n">to_proc</code> <code class="p">}</code>
<code class="n">steps</code><code class="o">.</code><code class="n">push</code><code class="p">(</code><code class="n">args</code><code class="o">[</code><code class="mi">4</code><code class="o">]</code><code class="p">)</code> <code class="k">unless</code> <code class="n">args</code><code class="o">[</code><code class="mi">4</code><code class="o">].</code><code class="n">nil?</code>
<code class="n">steps</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="n">define_method</code> <code class="ss">:multirec</code> <code class="k">do</code> <code class="o">|*</code><code class="n">args</code><code class="o">|</code>
<code class="n">cond_proc</code><code class="p">,</code> <code class="n">then_proc</code><code class="p">,</code> <code class="n">before_proc</code><code class="p">,</code> <code class="n">after_proc</code><code class="p">,</code> <code class="n">optional_value</code> <code class="o">=</code> <code class="n">separat</code><code class="p">\</code>
<code class="n">e_args</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">args</code><code class="p">)</code>
<code class="n">worker_proc</code> <code class="o">=</code> <code class="nb">lambda</code> <code class="k">do</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code>
<code class="k">if</code> <code class="n">cond_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">then_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="k">else</code>
<code class="n">after_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code>
<code class="n">before_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code><code class="o">.</code><code class="n">map</code> <code class="p">{</code> <code class="o">|</code><code class="n">sub_value</code><code class="o">|</code> <code class="n">worker_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">sub_va</code><code class="p">\</code>
<code class="n">lue</code><code class="p">)</code> <code class="p">}</code>
<code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">if</code> <code class="n">optional_value</code><code class="o">.</code><code class="n">nil?</code>
<code class="n">worker_proc</code>
<code class="k">else</code>
<code class="n">worker_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">optional_value</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="n">define_method</code> <code class="ss">:linrec</code> <code class="k">do</code> <code class="o">|*</code><code class="n">args</code><code class="o">|</code>
<code class="n">cond_proc</code><code class="p">,</code> <code class="n">then_proc</code><code class="p">,</code> <code class="n">before_proc</code><code class="p">,</code> <code class="n">after_proc</code><code class="p">,</code> <code class="n">optional_value</code> <code class="o">=</code> <code class="n">separat</code><code class="p">\</code>
<code class="n">e_args</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">args</code><code class="p">)</code>
<code class="n">worker_proc</code> <code class="o">=</code> <code class="nb">lambda</code> <code class="k">do</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code>
<code class="n">trivial_parts</code><code class="p">,</code> <code class="n">sub_problem</code> <code class="o">=</code> <code class="o">[]</code><code class="p">,</code> <code class="n">value</code>
<code class="k">while</code> <code class="o">!</code><code class="n">cond_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">sub_problem</code><code class="p">)</code>
<code class="n">trivial_part</code><code class="p">,</code> <code class="n">sub_problem</code> <code class="o">=</code> <code class="n">before_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">sub_problem</code><code class="p">)</code>
<code class="n">trivial_parts</code><code class="o">.</code><code class="n">unshift</code><code class="p">(</code><code class="n">trivial_part</code><code class="p">)</code>
<code class="k">end</code>
<code class="n">trivial_parts</code><code class="o">.</code><code class="n">unshift</code><code class="p">(</code><code class="n">then_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">sub_problem</code><code class="p">))</code>
<code class="n">trivial_parts</code><code class="o">.</code><code class="n">inject</code> <code class="k">do</code> <code class="o">|</code><code class="n">recombined</code><code class="p">,</code> <code class="n">trivial_part</code><code class="o">|</code>
<code class="n">after_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">trivial_part</code><code class="p">,</code> <code class="n">recombined</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">if</code> <code class="n">optional_value</code><code class="o">.</code><code class="n">nil?</code>
<code class="n">worker_proc</code>
<code class="k">else</code>
<code class="n">worker_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">optional_value</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="kp">module_function</code> <code class="ss">:multirec</code><code class="p">,</code> <code class="ss">:linrec</code>
<code class="k">end</code>
</pre></div>
<hr /></div>
<p>Now when we have trivial lambdas, we can use nice syntactic sugar to express them. <code>string_to_proc</code> is <strong>not</strong> part of our recursive combinators, but making recursive combinators flexible, we make it &#x201C;play well with others,&#x201D; which is a win for our code. </p>
<h3 section-num="8.8" id="separating-implementation-from-declaration"><span class="section-number">8.8 </span>Separating Implementation from Declaration</h3>
<p>In Refactoring Methods with Recursive Combinators, we read the claim that by separating the recursion implementation from the declaration of how to perform the steps of an algorithm like <code>#rotate</code>, we leave ourselves the opportunity to improve the performance of our implementation without the risk of adding bugs to our declaration.</p>
<p>In other words, we can optimize <code>linrec</code> if we want to. Well, we want to. So what we&#x2019;re going to do is optimize its performance by trading time for space. Let&#x2019;s have a quick look at the <code>worker_proc</code> lambda inside of <code>linrec</code>:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">worker_proc</code> <code class="p">=</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code>
<code class="k">if</code> <code class="n">cond_proc</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">then_proc</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="k">else</code>
<code class="n">trivial_part</code><code class="p">,</code> <code class="n">sub_problem</code> <code class="p">=</code> <code class="n">before_proc</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">value</code><code class="p">)</code>
<code class="n">after_proc</code><code class="p">.</code><code class="n">call</code><code class="p">(</code>
<code class="n">trivial_part</code><code class="p">,</code> <code class="n">worker_proc</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">sub_problem</code><code class="p">)</code>
<code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
</pre></div>
</div>
<p>As you can see, it is recursive, it calls itself to solve each sub-problem. And here is an iterative replacement:</p>
<div class="code-block">
<div class="highlight"><pre><code class="n">worker_proc</code> <code class="p">=</code> <code class="n">lambda</code> <code class="n">do</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code>
<code class="n">trivial_parts</code><code class="p">,</code> <code class="n">sub_problem</code> <code class="p">=</code> <code class="p">[],</code> <code class="n">value</code>
<code class="k">while</code> !<code class="n">cond_proc</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">sub_problem</code><code class="p">)</code>
<code class="n">trivial_part</code><code class="p">,</code> <code class="n">sub_problem</code> <code class="p">=</code> <code class="n">before_proc</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">sub_problem</code><code class="p">)</code>
<code class="n">trivial_parts</code><code class="p">.</code><code class="n">unshift</code><code class="p">(</code><code class="n">trivial_part</code><code class="p">)</code>
<code class="k">end</code>
<code class="n">trivial_parts</code><code class="p">.</code><code class="n">unshift</code><code class="p">(</code><code class="n">then_proc</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">sub_problem</code><code class="p">))</code>
<code class="n">trivial_parts</code><code class="p">.</code><code class="n">inject</code> <code class="n">do</code> <code class="o">|</code><code class="n">recombined</code><code class="p">,</code> <code class="n">trivial_part</code><code class="o">|</code>
<code class="n">after_proc</code><code class="p">.</code><code class="n">call</code><code class="p