Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

file 185 lines (149 sloc) 18.717 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
<?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>3 The Thrush</title>
<link href="stylesheet.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="leanpub-main">
<h2 section-num="3" id="the-thrush"><span class="section-number">3 </span>The Thrush</h2>

<p>In Combinatory Logic, the thrush is an extremely simple <em>permuting</em> combinator; it reverses the normal order of evaluation. The thrush is written <code>Txy = yx</code>. It <em>reverses</em> evaluation. In Ruby terms,</p>

<div class="code-block">
<div class="highlight"><pre><code class="n">thrush</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">a_value</code><code class="p">).</code><code class="n">call</code><code class="p">(</code><code class="n">a_proc</code><code class="p">)</code>
  <code class="p">=</code><code class="o">&gt;</code> <code class="n">a_proc</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">a_value</code><code class="p">)</code>
</pre></div>

</div>

<p>In <a href="http://weblog.raganwald.com/2008/01/no-detail-too-small.html">No Detail Too Small</a>, I defined <code>Object#into</code>, an implementation of the thrush as a Ruby method:</p>

<div class="code-block">
<div class="highlight"><pre><code class="n">class</code> <code class="n">Object</code>
  <code class="n">def</code> <code class="n">into</code> <code class="n">expr</code> <code class="p">=</code> <code class="n">nil</code>
    <code class="n">expr</code><code class="p">.</code><code class="n">nil</code>? ? <code class="n">yield</code><code class="p">(</code><code class="n">self</code><code class="p">)</code> <code class="p">:</code> <code class="n">expr</code><code class="p">.</code><code class="n">to_proc</code><code class="p">.</code><code class="n">call</code><code class="p">(</code><code class="n">self</code><code class="p">)</code>
  <code class="k">end</code>
<code class="k">end</code>
</pre></div>

</div>

<p>If you are in the habit of violating the <a href="http://en.wikipedia.org/wiki/Law_of_Demeter">Law of Demeter</a>, you can use <code>#into</code> to make an expression read consistently from left to right. For example, this code:</p>

<div class="code-block">
<div class="highlight"><pre><code class="n">lambda</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="o">|</code> <code class="n">x</code> <code class="o">*</code> <code class="n">x</code> <code class="p">}.</code><code class="n">call</code><code class="p">((</code>1<code class="p">..</code>100<code class="p">).</code><code class="n">select</code><code class="p">(</code><code class="o">&amp;</code><code class="p">:</code><code class="n">odd</code>?<code class="p">).</code><code class="n">inject</code><code class="p">(</code><code class="o">&amp;</code><code class="p">:</code><code class="o">+</code><code class="p">))</code>
</pre></div>

</div>

<p>Reads &#x201C;Square (take the numbers from 1 to 100, select the odd ones, and take the sum of those).&#x201D; Confusing. Whereas with <code>#into</code>, you can write:</p>

<div class="code-block">
<div class="highlight"><pre><code class="p">(</code>1<code class="p">..</code>100<code class="p">).</code><code class="n">select</code><code class="p">(</code><code class="o">&amp;</code><code class="p">:</code><code class="n">odd</code>?<code class="p">).</code><code class="n">inject</code><code class="p">(</code><code class="o">&amp;</code><code class="p">:</code><code class="o">+</code><code class="p">).</code><code class="n">into</code> <code class="p">{</code> <code class="o">|</code><code class="n">x</code><code class="o">|</code> <code class="n">x</code> <code class="o">*</code> <code class="n">x</code> <code class="p">}</code>
</pre></div>

</div>

<p>Which reads &#x201C;Take the numbers from 1 to 100, keep the odd ones, take the sum of those, and then answer the square of that number.&#x201D;</p>

<p>A permuting combinator like <code>#into</code> is not strictly necessary when you have parentheses or local variables. Which is kind of interesting, because it shows that if you have permuting combinators, you can model parentheses and local variables.</p>

<p>But we are not interested in theory. <code>#into</code> may be equivalent to what we can accomplish with other means, but it is useful to us if we feel it makes the code clearer and easier to understand. Sometimes a longer expression should be broken into multiple small expressions to make it easier to understand. Sometimes it can be reordered using tools like <code>#into</code>.</p>

<h3 section-num="3.1" id="let"><span class="section-number">3.1 </span>Let</h3>

<p><code>Object#into</code> defines the thrush as a method that takes a block, lambda, or anything that can become a block or lambda as its argument. There is another way to formulate a Thrush:</p>

<div class="code-block">
<div class="highlight"><pre><code class="n">class</code> <code class="n">Kernel</code>
  <code class="n">def</code> <code class="n">let</code> <code class="n">it</code>
    <code class="n">yield</code> <code class="n">it</code>
  <code class="k">end</code>
<code class="k">end</code>
</pre></div>

</div>

<p>It&#x2019;s remarkably simple, so simple that it appears to be less useful than <code>#into</code>. The example above would look like this if we used <code>let</code>:</p>

<div class="code-block">
<div class="highlight"><pre><code class="n">let</code> <code class="p">(</code>1<code class="p">..</code>100<code class="p">).</code><code class="n">select</code><code class="p">(</code><code class="o">&amp;</code><code class="p">:</code><code class="n">odd</code>?<code class="p">).</code><code class="n">inject</code><code class="p">(</code><code class="o">&amp;</code><code class="p">:</code><code class="o">+</code><code class="p">)</code> <code class="n">do</code> <code class="o">|</code><code class="n">x</code><code class="o">|</code>
<code class="n">x</code> <code class="o">*</code> <code class="n">x</code>
<code class="k">end</code>
</pre></div>

</div>

<p>How does that help? I&#x2019;ll let you in on a secret: Ruby 1.9 changes the game. In Ruby 1.8, <code>x</code> is local to the surrounding method, so it doesn&#x2019;t help. But in Ruby 1.9, <code>x</code> is a <em>block local variable</em>, meaning that it does not clobber an existing variable. So in Ruby 1.8:</p>

<div class="code-block">
<div class="highlight"><pre><code class="n">def</code> <code class="n">say_the_square_of_the_sum_of_the_odd_numbers</code><code class="p">(</code><code class="n">x</code><code class="p">)</code>
<code class="n">sotos</code> <code class="p">=</code> <code class="n">let</code> <code class="p">(</code>1<code class="p">..</code><code class="n">x</code><code class="p">).</code><code class="n">select</code><code class="p">(</code><code class="o">&amp;</code><code class="p">:</code><code class="n">odd</code>?<code class="p">).</code><code class="n">inject</code><code class="p">(</code><code class="o">&amp;</code><code class="p">:</code><code class="o">+</code><code class="p">)</code> <code class="n">do</code> <code class="o">|</code><code class="n">x</code><code class="o">|</code>
<code class="n">x</code> <code class="o">*</code> <code class="n">x</code>
<code class="k">end</code>
"<code class="n">The</code> <code class="n">square</code> <code class="n">of</code> <code class="n">the</code> <code class="n">sum</code> <code class="n">of</code> <code class="n">the</code> <code class="n">odd</code> <code class="n">numbers</code> <code class="n">from</code> 1<code class="p">..</code>#<code class="p">{</code><code class="n">x</code><code class="p">}</code> <code class="n">is</code> #<code class="p">{</code><code class="n">sotos</code><code class="p">}</code>"
<code class="k">end</code>

<code class="n">say_the_square_of_the_sum_of_the_odd_numbers</code><code class="p">(</code>10<code class="p">)</code>
 <code class="p">=</code><code class="o">&gt;</code> "<code class="n">The</code> <code class="n">square</code> <code class="n">of</code> <code class="n">the</code> <code class="n">sum</code> <code class="n">of</code> <code class="n">the</code> <code class="n">odd</code> <code class="n">numbers</code> <code class="n">from</code> 1<code class="p">..</code>25 <code class="n">is</code> 625"
</pre></div>

</div>

<p><code>1..25</code>!? What happened here is that the <code>x</code> inside the block clobbered the value of the <code>x</code> parameter. Not good. In Ruby 1.9:</p>

<div class="code-block">
<div class="highlight"><pre><code class="n">say_the_square_of_the_sum_of_the_odd_numbers</code><code class="p">(</code>10<code class="p">)</code>
 <code class="p">=</code><code class="o">&gt;</code> "<code class="n">The</code> <code class="n">square</code> <code class="n">of</code> <code class="n">the</code> <code class="n">sum</code> <code class="n">of</code> <code class="n">the</code> <code class="n">odd</code> <code class="n">numbers</code> <code class="n">from</code> 1<code class="p">..</code>10 <code class="n">is</code> 625"
</pre></div>

</div>

<p>Much better, Ruby 1.9 creates a new scope inside the block and <code>x</code> is local to that block, <em>shadowing</em> the <code>x</code> parameter. Now we see a use for <code>let</code>:</p>

<div class="code-block">
<div class="highlight"><pre><code class="n">let</code><code class="p">(</code><code class="n">some_expression</code><code class="p">)</code> <code class="n">do</code> <code class="o">|</code><code class="n">my_block_local_variable</code><code class="o">|</code>
# <code class="p">...</code>
<code class="k">end</code>
</pre></div>

</div>

<p><code>let</code> creates a new scope and defines your block local variable inside the block. This <a href="http://weblog.raganwald.com/2007/11/programming-conventions-as-signals.html" title="Programming conventions as signals">signals</a> that the block local variable is not used elsewhere. Imperative methods can be easier to understand when they are composed of smaller blocks with well-defined dependencies between them. A variable local to the entire method creates a dependency across the entire method. A variable local to a block only creates dependencies within that block.</p>

<p>Although Ruby 1.8 does not enforce this behaviour, it can be useful to write code in this style as a signal to make the code easier to read.</p>

<p>
  <strong>Summary</strong>
</p>

<p>We have seen two formulations of the thrush combinator, <code>#into</code> and <code>let</code>. One is useful for making expressions more consistent and easier to read, the other for signaling the scope of block-local variables.</p>
</div>
<div id="leanpub-toc">
<h2>Table of Contents</h2>
<ol class="toc">
<li class="section"><a href="chap00.html#the-mit-license"><span class="section-number">0.1 </span>The MIT License</a></li>
<li class="section"><a href="chap00.html#preface"><span class="section-number">0.2 </span>Preface</a></li>
<li class="chapter"><a href="chap01.html#introduction"><span class="section-number">1 </span>Introduction</a></li>
<li class="chapter"><a href="chap02.html#kestrels"><span class="section-number">2 </span>Kestrels</a></li>
<li class="section"><a href="chap02.html#object-initializer-blocks"><span class="section-number">2.1 </span>Object initializer blocks</a></li>
<li class="section"><a href="chap02.html#inside-an-idiomatic-ruby-kestrel"><span class="section-number">2.2 </span>Inside, an idiomatic Ruby Kestrel</a></li>
<li class="section"><a href="chap02.html#the-enchaining-kestrel"><span class="section-number">2.3 </span>The Enchaining Kestrel</a></li>
<li class="section"><a href="chap02.html#the-obdurate-kestrel"><span class="section-number">2.4 </span>The Obdurate Kestrel</a></li>
<li class="section"><a href="chap02.html#kestrels-on-rails"><span class="section-number">2.5 </span>Kestrels on Rails</a></li>
<li class="section"><a href="chap02.html#rewriting-returning-in-rails"><span class="section-number">2.6 </span>Rewriting &#x201C;Returning&#x201D; in Rails</a></li>
<li class="chapter"><a href="chap03.html#the-thrush"><span class="section-number">3 </span>The Thrush</a></li>
<li class="section"><a href="chap03.html#let"><span class="section-number">3.1 </span>Let</a></li>
<li class="chapter"><a href="chap04.html#songs-of-the-cardinal"><span class="section-number">4 </span>Songs of the Cardinal</a></li>
<li class="section"><a href="chap04.html#building-a-cardinal-in-ruby"><span class="section-number">4.1 </span>Building a Cardinal in Ruby</a></li>
<li class="chapter"><a href="chap05.html#quirky-birds-and-meta-syntactic-programming"><span class="section-number">5 </span>Quirky Birds and Meta-Syntactic Programming</a></li>
<li class="section"><a href="chap05.html#a-limited-interpretation-of-the-quirky-bird-in-ruby"><span class="section-number">5.1 </span>A limited interpretation of the Quirky Bird in Ruby</a></li>
<li class="section"><a href="chap05.html#embracing-the-quirky-bird"><span class="section-number">5.2 </span>Embracing the Quirky Bird</a></li>
<li class="section"><a href="chap05.html#andand-even-more"><span class="section-number">5.3 </span>Andand even more</a></li>
<li class="chapter"><a href="chap06.html#aspect-oriented-programming-in-ruby-using-combinator-birds"><span class="section-number">6 </span>Aspect-Oriented Programming in Ruby using Combinator Birds</a></li>
<li class="section"><a href="chap06.html#giving-methods-advice"><span class="section-number">6.1 </span>Giving methods advice</a></li>
<li class="section"><a href="chap06.html#the-super-keyword-perhaps-youve-heard-of-it"><span class="section-number">6.2 </span>The super keyword, perhaps you&#x2019;ve heard of it?</a></li>
<li class="section"><a href="chap06.html#the-queer-bird"><span class="section-number">6.3 </span>The Queer Bird</a></li>
<li class="chapter"><a href="chap07.html#mockingbirds"><span class="section-number">7 </span>Mockingbirds</a></li>
<li class="section"><a href="chap07.html#duplicative-combinators"><span class="section-number">7.1 </span>Duplicative Combinators</a></li>
<li class="section"><a href="chap07.html#recursive-lambdas-in-ruby"><span class="section-number">7.2 </span>Recursive Lambdas in Ruby</a></li>
<li class="section"><a href="chap07.html#recursive-combinatorics"><span class="section-number">7.3 </span>Recursive Combinatorics</a></li>
<li class="section"><a href="chap07.html#recursive-combinators-in-idiomatic-ruby"><span class="section-number">7.4 </span>Recursive Combinators in Idiomatic Ruby</a></li>
<li class="section"><a href="chap07.html#the-mockingbird"><span class="section-number">7.5 </span>The Mockingbird</a></li>
<li class="chapter"><a href="chap08.html#refactoring-methods-with-recursive-combinators"><span class="section-number">8 </span>Refactoring Methods with Recursive Combinators</a></li>
<li class="section"><a href="chap08.html#divide-and-conquer"><span class="section-number">8.1 </span>Divide and Conquer</a></li>
<li class="section"><a href="chap08.html#the-merge-sort"><span class="section-number">8.2 </span>The Merge Sort</a></li>
<li class="section"><a href="chap08.html#separating-declaration-from-implementation"><span class="section-number">8.3 </span>Separating Declaration from Implementation</a></li>
<li class="section"><a href="chap08.html#practical-recursive-combinators"><span class="section-number">8.4 </span>Practical Recursive Combinators</a></li>
<li class="section"><a href="chap08.html#spicing-things-up"><span class="section-number">8.5 </span>Spicing things up</a></li>
<li class="section"><a href="chap08.html#building-on-a-legacy"><span class="section-number">8.6 </span>Building on a legacy</a></li>
<li class="section"><a href="chap08.html#seriously"><span class="section-number">8.7 </span>Seriously</a></li>
<li class="section"><a href="chap08.html#separating-implementation-from-declaration"><span class="section-number">8.8 </span>Separating Implementation from Declaration</a></li>
<li class="section"><a href="chap08.html#a-really-simple-recursive-combinator"><span class="section-number">8.9 </span>A Really Simple Recursive Combinator</a></li>
<li class="chapter"><a href="chap09.html#you-cant-be-serious"><span class="section-number">9 </span>You can&#x2019;t be serious!?</a></li>
<li class="section"><a href="chap09.html#string-to-proc"><span class="section-number">9.1 </span>String to Proc</a></li>
<li class="section"><a href="chap09.html#the-message"><span class="section-number">9.2 </span>The Message</a></li>
<li class="chapter"><a href="chap10.html#the-hopelessly-egocentric-book-chapter"><span class="section-number">10 </span>The Hopelessly Egocentric Book Chapter</a></li>
<li class="section"><a href="chap10.html#object-oriented-egocentricity"><span class="section-number">10.1 </span>Object-oriented egocentricity</a></li>
<li class="chapter"><a href="chap11.html#bonus-chapter-separating-concerns-in-coffeescript-using-aspect-oriented-programming"><span class="section-number">11 </span>Bonus Chapter: Separating Concerns in Coffeescript using Aspect-Oriented Programming</a></li>
<li class="chapter"><a href="chap12.html#appendix-finding-joy-in-combinators"><span class="section-number">12 </span>Appendix: Finding Joy in Combinators</a></li>
<li class="section"><a href="chap12.html#languages-for-combinatorial-logic"><span class="section-number">12.1 </span>Languages for combinatorial logic</a></li>
<li class="section"><a href="chap12.html#concatenative-languages"><span class="section-number">12.2 </span>Concatenative languages</a></li>
<li class="chapter"><a href="chap13.html#appendix-source-code"><span class="section-number">13 </span>Appendix: Source Code</a></li>
<li class="section"><a href="chap13.html#kestrels-1"><span class="section-number">13.1 </span>kestrels</a></li>
<li class="section"><a href="chap13.html#thrushes"><span class="section-number">13.2 </span>thrushes</a></li>
<li class="section"><a href="chap13.html#the-cardinal"><span class="section-number">13.3 </span>the cardinal</a></li>
<li class="section"><a href="chap13.html#quirky-birds"><span class="section-number">13.4 </span>quirky birds</a></li>
<li class="section"><a href="chap13.html#bluebirds"><span class="section-number">13.5 </span>bluebirds</a></li>
<li class="chapter"><a href="chap14.html#about-the-author"><span class="section-number">14 </span>About The Author</a></li>
<li class="section"><a href="chap14.html#contact"><span class="section-number">14.1 </span>contact</a></li>
</ol>
</div>
</body>
</html>
Something went wrong with that request. Please try again.