Find file
Fetching contributors…
Cannot retrieve contributors at this time
873 lines (800 sloc) 71.5 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>13 Appendix: Source Code</title>
<link href="stylesheet.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="leanpub-main">
<h2 section-num="13" id="appendix-source-code"><span class="section-number">13 </span>Appendix: Source Code</h2>
<p>All source code is published under the following license:</p>
<div class="code-block">
<div class="highlight"><pre><code class="c"># The MIT License</code>
<code class="c"># </code>
<code class="c"># All contents Copyright (c) 2004-2008 Reginald Braithwaite</code>
<code class="c"># &lt;http://braythwayt.com&gt; except as otherwise noted.</code>
<code class="c"># </code>
<code class="c"># Permission is hereby granted, free of charge, to any person obtaining a c\</code>
<code class="n">opy</code>
<code class="c"># of this software and associated documentation files (the "Software"), to \</code>
<code class="nb">deal</code>
<code class="c"># in the Software without restriction, including without limitation the rig\</code>
<code class="n">hts</code>
<code class="c"># to use, copy, modify, merge, publish, distribute, sublicense, and/or sell</code>
<code class="c"># copies of the Software, and to permit persons to whom the Software is</code>
<code class="c"># furnished to do so, subject to the following conditions:</code>
<code class="c"># </code>
<code class="c"># The above copyright notice and this permission notice shall be included i\</code>
<code class="n">n</code>
<code class="c"># all copies or substantial portions of the Software.</code>
<code class="c"># </code>
<code class="c"># THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS O\</code>
<code class="n">R</code>
<code class="c"># IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</code>
<code class="c"># FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL T\</code>
<code class="n">HE</code>
<code class="c"># AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</code>
<code class="c"># LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING F\</code>
<code class="n">ROM</code><code class="p">,</code>
<code class="c"># OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN</code>
<code class="c"># THE SOFTWARE.</code>
<code class="c"># </code>
<code class="c"># http://www.opensource.org/licenses/mit-license.php</code>
</pre></div>
</div>
<h3 section-num="13.1" id="kestrels-1"><span class="section-number">13.1 </span>kestrels</h3>
<div class="code-block">
<p class="codeblock-title">returning.rb</p>
<hr /><div class="highlight"><pre><code class="c1"># The MIT License</code>
<code class="c1"># </code>
<code class="c1"># All contents Copyright (c) 2004-2008 Reginald Braithwaite</code>
<code class="c1"># &lt;http://braythwayt.com&gt; except as otherwise noted.</code>
<code class="c1"># </code>
<code class="c1"># Permission is hereby granted, free of charge, to any person obtaining a c\</code>
<code class="n">opy</code>
<code class="c1"># of this software and associated documentation files (the "Software"), to \</code>
<code class="n">deal</code>
<code class="c1"># in the Software without restriction, including without limitation the rig\</code>
<code class="n">hts</code>
<code class="c1"># to use, copy, modify, merge, publish, distribute, sublicense, and/or sell</code>
<code class="c1"># copies of the Software, and to permit persons to whom the Software is</code>
<code class="c1"># furnished to do so, subject to the following conditions:</code>
<code class="c1"># </code>
<code class="c1"># The above copyright notice and this permission notice shall be included i\</code>
<code class="n">n</code>
<code class="c1"># all copies or substantial portions of the Software.</code>
<code class="c1"># </code>
<code class="c1"># THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS O\</code>
<code class="n">R</code>
<code class="c1"># IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</code>
<code class="c1"># FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL T\</code>
<code class="no">HE</code>
<code class="c1"># AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</code>
<code class="c1"># LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING F\</code>
<code class="no">ROM</code><code class="p">,</code>
<code class="c1"># OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN</code>
<code class="c1"># THE SOFTWARE.</code>
<code class="c1"># </code>
<code class="c1"># http://www.opensource.org/licenses/mit-license.php</code>
<code class="k">unless</code> <code class="nb">respond_to?</code><code class="p">(</code><code class="ss">:returning</code><code class="p">)</code>
<code class="k">def</code> <code class="nf">returning</code><code class="p">(</code><code class="n">it</code><code class="p">)</code>
<code class="k">yield</code> <code class="n">it</code>
<code class="n">it</code>
<code class="k">end</code>
<code class="k">end</code>
</pre></div>
<hr /></div>
<h3 section-num="13.2" id="thrushes"><span class="section-number">13.2 </span>thrushes</h3>
<div class="code-block">
<p class="codeblock-title">into.rb</p>
<hr /><div class="highlight"><pre><code class="k">class</code> <code class="nc">Object</code>
<code class="k">def</code> <code class="nf">into</code> <code class="n">expr</code> <code class="o">=</code> <code class="kp">nil</code>
<code class="n">expr</code><code class="o">.</code><code class="n">nil?</code> <code class="p">?</code> <code class="k">yield</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code> <code class="p">:</code> <code class="n">expr</code><code class="o">.</code><code class="n">to_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
</pre></div>
<hr /></div>
<div class="code-block">
<p class="codeblock-title">let.rb</p>
<hr /><div class="highlight"><pre><code class="k">class</code> <code class="nc">Kernel</code>
<code class="k">def</code> <code class="nf">let</code> <code class="n">it</code>
<code class="k">yield</code> <code class="n">it</code>
<code class="k">end</code>
<code class="k">end</code>
</pre></div>
<hr /></div>
<h3 section-num="13.3" id="the-cardinal"><span class="section-number">13.3 </span>the cardinal</h3>
<div class="code-block">
<p class="codeblock-title">cardinal.rb</p>
<hr /><div class="highlight"><pre><code class="k">def</code> <code class="nf">cardinal_define</code><code class="p">(</code><code class="nb">name</code><code class="p">,</code> <code class="o">&amp;</code><code class="n">proc_over_proc</code><code class="p">)</code>
<code class="n">define_method_taking_block</code><code class="p">(</code><code class="nb">name</code><code class="p">)</code> <code class="k">do</code> <code class="o">|</code><code class="n">a_value</code><code class="p">,</code> <code class="n">a_proc</code><code class="o">|</code>
<code class="n">proc_over_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">a_proc</code><code class="p">)</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">a_value</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="c1"># method_body_proc should expect (a_value, a_proc)</code>
<code class="c1"># see http://coderrr.wordpress.com/2008/10/29/using-define_method-with-bloc\</code>
<code class="n">ks</code><code class="o">-</code><code class="k">in</code><code class="o">-</code><code class="n">ruby</code><code class="o">-</code><code class="mi">18</code><code class="o">/</code>
<code class="k">def</code> <code class="nf">define_method_taking_block</code><code class="p">(</code><code class="nb">name</code><code class="p">,</code> <code class="o">&amp;</code><code class="n">method_body_proc</code><code class="p">)</code>
<code class="nb">self</code><code class="o">.</code><code class="n">class</code><code class="o">.</code><code class="n">send</code> <code class="ss">:define_method</code><code class="p">,</code> <code class="s2">"__cardinal_helper_</code><code class="si">#{</code><code class="nb">name</code><code class="si">}</code><code class="s2">__"</code><code class="p">,</code> <code class="n">method_bod</code><code class="p">\</code>
<code class="n">y_proc</code>
<code class="nb">eval</code> <code class="o">&lt;&lt;-</code><code class="no">EOM</code>
<code class="sh"> def #{name}(a_value, &amp;a_proc)</code>
<code class="sh"> __cardinal_helper_#{name}__(a_value, a_proc)</code>
<code class="sh"> end</code>
<code class="no"> EOM</code>
<code class="k">end</code>
</pre></div>
<hr /></div>
<h3 section-num="13.4" id="quirky-birds"><span class="section-number">13.4 </span>quirky birds</h3>
<div class="code-block">
<p class="codeblock-title">andand.rb</p>
<hr /><div class="highlight"><pre><code class="k">module</code> <code class="nn">AndAnd</code>
<code class="c1"># This module is included in Object, so each of these methods are added</code>
<code class="c1"># to Object when you require 'andand'. Each method is an *adverb*: they a\</code>
<code class="n">re</code>
<code class="c1"># intended to be enchained with another method, such as receiver.adverb.m\</code>
<code class="n">ethod</code>
<code class="c1">#</code>
<code class="c1"># The purpose of an adverb is to modify what the primary method returns.</code>
<code class="c1">#</code>
<code class="c1"># Adverbs also take blocks or procs, passing the receiver as an argument \</code>
<code class="n">to</code> <code class="n">the</code>
<code class="c1"># block or proc. They retain the same semantics with a block or proc as t\</code>
<code class="n">hey</code>
<code class="c1"># do with a method. This behaviour weakly resembles a monad.</code>
<code class="k">module</code> <code class="nn">ObjectGoodies</code>
<code class="c1"># Returns nil if its receiver is nil, regardless of whether nil actuall\</code>
<code class="n">y</code> <code class="n">handles</code> <code class="n">the</code>
<code class="c1"># actual method ot what it might return.</code>
<code class="c1">#</code>
<code class="c1"># 'foo'.andand.size =&gt; 3</code>
<code class="c1"># nil.andand.size =&gt; nil</code>
<code class="c1"># 'foo'.andand { |s| s &lt;&lt; 'bar' } =&gt; 'foobar'</code>
<code class="c1"># nil.andand { |s| s &lt;&lt; 'bar' } =&gt; nil</code>
<code class="k">def</code> <code class="nf">andand</code> <code class="p">(</code><code class="nb">p</code> <code class="o">=</code> <code class="kp">nil</code><code class="p">)</code>
<code class="k">if</code> <code class="nb">self</code>
<code class="k">if</code> <code class="nb">block_given?</code>
<code class="k">yield</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code>
<code class="k">elsif</code> <code class="nb">p</code>
<code class="nb">p</code><code class="o">.</code><code class="n">to_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code>
<code class="k">else</code>
<code class="nb">self</code>
<code class="k">end</code>
<code class="k">else</code>
<code class="k">if</code> <code class="nb">block_given?</code> <code class="ow">or</code> <code class="nb">p</code>
<code class="nb">self</code>
<code class="k">else</code>
<code class="no">MockReturningMe</code><code class="o">.</code><code class="n">new</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="c1"># Invokes the method and returns the receiver if nothing is raised. The\</code>
<code class="n">refore</code><code class="p">,</code>
<code class="c1"># the purpose of calling the method is strictly for side effects. In th\</code>
<code class="n">e</code> <code class="n">block</code>
<code class="c1"># form, it resembles #tap from Ruby 1.9, and is useful for debugging. I\</code>
<code class="n">t</code> <code class="n">also</code>
<code class="c1"># resembles #returning from Rails, with slightly different syntax.</code>
<code class="c1">#</code>
<code class="c1"># Object.new.me do |o|</code>
<code class="c1"># def o.foo</code>
<code class="c1"># 'foo'</code>
<code class="c1"># end</code>
<code class="c1"># end</code>
<code class="c1"># =&gt; your new object</code>
<code class="c1">#</code>
<code class="c1"># In the method form, it is handy for chaining methods that don't ordin\</code>
<code class="n">arily</code>
<code class="c1"># return the receiver:</code>
<code class="c1">#</code>
<code class="c1"># [1, 2, 3, 4, 5].me.pop.reverse</code>
<code class="c1"># =&gt; [4, 3, 2, 1]</code>
<code class="k">def</code> <code class="nf">me</code> <code class="p">(</code><code class="nb">p</code> <code class="o">=</code> <code class="kp">nil</code><code class="p">)</code>
<code class="k">if</code> <code class="nb">block_given?</code>
<code class="k">yield</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code>
<code class="nb">self</code>
<code class="k">elsif</code> <code class="nb">p</code>
<code class="nb">p</code><code class="o">.</code><code class="n">to_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code>
<code class="nb">self</code>
<code class="k">else</code>
<code class="no">ProxyReturningMe</code><code class="o">.</code><code class="n">new</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">unless</code> <code class="no">Object</code><code class="o">.</code><code class="n">instance_methods</code><code class="o">.</code><code class="n">include?</code><code class="p">(</code><code class="s1">'tap'</code><code class="p">)</code>
<code class="k">alias</code> <code class="ss">:tap</code> <code class="ss">:me</code>
<code class="k">end</code>
<code class="c1"># Does not invoke the method or block and returns the receiver.</code>
<code class="c1"># Useful for comemnting stuff out, especially if you are using #me for</code>
<code class="c1"># debugging purposes: change the .me to .dont and the semantics of your</code>
<code class="c1"># program are unchanged.</code>
<code class="c1">#</code>
<code class="c1"># [1, 2, 3, 4, 5].me { |x| p x }</code>
<code class="c1"># =&gt; prints and returns the array</code>
<code class="c1"># [1, 2, 3, 4, 5].dont { |x| p x }</code>
<code class="c1"># =&gt; returns the array without printing it</code>
<code class="k">def</code> <code class="nf">dont</code> <code class="p">(</code><code class="nb">p</code> <code class="o">=</code> <code class="kp">nil</code><code class="p">)</code>
<code class="k">if</code> <code class="nb">block_given?</code>
<code class="nb">self</code>
<code class="k">elsif</code> <code class="nb">p</code>
<code class="nb">self</code>
<code class="k">else</code>
<code class="no">MockReturningMe</code><code class="o">.</code><code class="n">new</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">class</code> <code class="nc">Object</code>
<code class="kp">include</code> <code class="no">AndAnd</code><code class="o">::</code><code class="no">ObjectGoodies</code>
<code class="k">end</code>
<code class="k">unless</code> <code class="no">Module</code><code class="o">.</code><code class="n">constants</code><code class="o">.</code><code class="n">include?</code><code class="p">(</code><code class="s1">'BlankSlate'</code><code class="p">)</code>
<code class="k">if</code> <code class="no">Module</code><code class="o">.</code><code class="n">constants</code><code class="o">.</code><code class="n">include?</code><code class="p">(</code><code class="s1">'BasicObject'</code><code class="p">)</code>
<code class="k">module</code> <code class="nn">AndAnd</code>
<code class="k">class</code> <code class="nc">BlankSlate</code> <code class="o">&lt;</code> <code class="no">BasicObject</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">else</code>
<code class="k">module</code> <code class="nn">AndAnd</code>
<code class="k">class</code> <code class="nc">BlankSlate</code>
<code class="k">def</code> <code class="nc">self</code><code class="o">.</code><code class="nf">wipe</code>
<code class="nb">instance_methods</code><code class="o">.</code><code class="n">reject</code> <code class="p">{</code> <code class="o">|</code><code class="n">m</code><code class="o">|</code> <code class="n">m</code> <code class="o">=~</code> <code class="sr">/^__/</code> <code class="p">}</code><code class="o">.</code><code class="n">each</code> <code class="p">{</code> <code class="o">|</code><code class="n">m</code><code class="o">|</code> <code class="n">undef_metho</code><code class="p">\</code>
<code class="n">d</code> <code class="n">m</code> <code class="p">}</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nf">initialize</code>
<code class="no">BlankSlate</code><code class="o">.</code><code class="n">wipe</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">module</code> <code class="nn">AndAnd</code>
<code class="c1"># A proxy that returns its target without invoking the method you</code>
<code class="c1"># invoke. Useful for nil.andand and #dont</code>
<code class="k">class</code> <code class="nc">MockReturningMe</code> <code class="o">&lt;</code> <code class="no">BlankSlate</code>
<code class="k">def</code> <code class="nf">initialize</code><code class="p">(</code><code class="n">me</code><code class="p">)</code>
<code class="k">super</code><code class="p">()</code>
<code class="vi">@me</code> <code class="o">=</code> <code class="n">me</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nf">method_missing</code><code class="p">(</code><code class="o">*</code><code class="n">args</code><code class="p">)</code>
<code class="vi">@me</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="c1"># A proxy that returns its target after invoking the method you</code>
<code class="c1"># invoke. Useful for #me</code>
<code class="k">class</code> <code class="nc">ProxyReturningMe</code> <code class="o">&lt;</code> <code class="no">BlankSlate</code>
<code class="k">def</code> <code class="nf">initialize</code><code class="p">(</code><code class="n">me</code><code class="p">)</code>
<code class="k">super</code><code class="p">()</code>
<code class="vi">@me</code> <code class="o">=</code> <code class="n">me</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nf">method_missing</code><code class="p">(</code><code class="n">sym</code><code class="p">,</code> <code class="o">*</code><code class="n">args</code><code class="p">,</code> <code class="o">&amp;</code><code class="n">block</code><code class="p">)</code>
<code class="vi">@me</code><code class="o">.</code><code class="n">__send__</code><code class="p">(</code><code class="n">sym</code><code class="p">,</code> <code class="o">*</code><code class="n">args</code><code class="p">,</code> <code class="o">&amp;</code><code class="n">block</code><code class="p">)</code>
<code class="vi">@me</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
</pre></div>
<hr /></div>
<div class="code-block">
<p class="codeblock-title">blank_slate.rb</p>
<hr /><div class="highlight"><pre><code class="c1"># The MIT License</code>
<code class="c1"># </code>
<code class="c1"># All contents Copyright (c) 2004-2008 Reginald Braithwaite</code>
<code class="c1"># &lt;http://braythwayt.com&gt; except as otherwise noted.</code>
<code class="c1"># </code>
<code class="c1"># Permission is hereby granted, free of charge, to any person obtaining a c\</code>
<code class="n">opy</code>
<code class="c1"># of this software and associated documentation files (the "Software"), to \</code>
<code class="n">deal</code>
<code class="c1"># in the Software without restriction, including without limitation the rig\</code>
<code class="n">hts</code>
<code class="c1"># to use, copy, modify, merge, publish, distribute, sublicense, and/or sell</code>
<code class="c1"># copies of the Software, and to permit persons to whom the Software is</code>
<code class="c1"># furnished to do so, subject to the following conditions:</code>
<code class="c1"># </code>
<code class="c1"># The above copyright notice and this permission notice shall be included i\</code>
<code class="n">n</code>
<code class="c1"># all copies or substantial portions of the Software.</code>
<code class="c1"># </code>
<code class="c1"># THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS O\</code>
<code class="n">R</code>
<code class="c1"># IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</code>
<code class="c1"># FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL T\</code>
<code class="no">HE</code>
<code class="c1"># AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</code>
<code class="c1"># LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING F\</code>
<code class="no">ROM</code><code class="p">,</code>
<code class="c1"># OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN</code>
<code class="c1"># THE SOFTWARE.</code>
<code class="c1"># </code>
<code class="c1"># http://www.opensource.org/licenses/mit-license.php</code>
<code class="k">unless</code> <code class="no">Module</code><code class="o">.</code><code class="n">constants</code><code class="o">.</code><code class="n">include?</code><code class="p">(</code><code class="s1">'BlankSlate'</code><code class="p">)</code>
<code class="k">if</code> <code class="no">Module</code><code class="o">.</code><code class="n">constants</code><code class="o">.</code><code class="n">include?</code><code class="p">(</code><code class="s1">'BasicObject'</code><code class="p">)</code>
<code class="k">class</code> <code class="nc">BlankSlate</code> <code class="o">&lt;</code> <code class="no">BasicObject</code>
<code class="k">end</code>
<code class="k">else</code>
<code class="k">class</code> <code class="nc">BlankSlate</code>
<code class="k">def</code> <code class="nc">self</code><code class="o">.</code><code class="nf">wipe</code>
<code class="nb">instance_methods</code><code class="o">.</code><code class="n">reject</code> <code class="p">{</code> <code class="o">|</code><code class="n">m</code><code class="o">|</code> <code class="n">m</code> <code class="o">=~</code> <code class="sr">/^__/</code> <code class="p">}</code><code class="o">.</code><code class="n">each</code> <code class="p">{</code> <code class="o">|</code><code class="n">m</code><code class="o">|</code> <code class="n">undef_method</code> <code class="p">\</code>
<code class="n">m</code> <code class="p">}</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nf">initialize</code>
<code class="no">BlankSlate</code><code class="o">.</code><code class="n">wipe</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>
<div class="code-block">
<p class="codeblock-title">quirky_bird.rb</p>
<hr /><div class="highlight"><pre><code class="c1"># The MIT License</code>
<code class="c1"># </code>
<code class="c1"># All contents Copyright (c) 2004-2008 Reginald Braithwaite</code>
<code class="c1"># &lt;http://braythwayt.com&gt; except as otherwise noted.</code>
<code class="c1"># </code>
<code class="c1"># Permission is hereby granted, free of charge, to any person obtaining a c\</code>
<code class="n">opy</code>
<code class="c1"># of this software and associated documentation files (the "Software"), to \</code>
<code class="n">deal</code>
<code class="c1"># in the Software without restriction, including without limitation the rig\</code>
<code class="n">hts</code>
<code class="c1"># to use, copy, modify, merge, publish, distribute, sublicense, and/or sell</code>
<code class="c1"># copies of the Software, and to permit persons to whom the Software is</code>
<code class="c1"># furnished to do so, subject to the following conditions:</code>
<code class="c1"># </code>
<code class="c1"># The above copyright notice and this permission notice shall be included i\</code>
<code class="n">n</code>
<code class="c1"># all copies or substantial portions of the Software.</code>
<code class="c1"># </code>
<code class="c1"># THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS O\</code>
<code class="n">R</code>
<code class="c1"># IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</code>
<code class="c1"># FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL T\</code>
<code class="no">HE</code>
<code class="c1"># AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</code>
<code class="c1"># LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING F\</code>
<code class="no">ROM</code><code class="p">,</code>
<code class="c1"># OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN</code>
<code class="c1"># THE SOFTWARE.</code>
<code class="c1"># </code>
<code class="c1"># http://www.opensource.org/licenses/mit-license.php</code>
<code class="k">def</code> <code class="nf">quirky_bird_define</code><code class="p">(</code><code class="nb">name</code><code class="p">,</code> <code class="o">&amp;</code><code class="n">value_proc</code><code class="p">)</code>
<code class="n">define_method_taking_block</code><code class="p">(</code><code class="nb">name</code><code class="p">)</code> <code class="k">do</code> <code class="o">|</code><code class="n">a_value</code><code class="p">,</code> <code class="n">a_proc</code><code class="o">|</code>
<code class="n">a_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">value_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">a_value</code><code class="p">))</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="c1"># method_body_proc should expect (a_value, a_proc)</code>
<code class="c1"># see http://coderrr.wordpress.com/2008/10/29/using-define_method-with-bloc\</code>
<code class="n">ks</code><code class="o">-</code><code class="k">in</code><code class="o">-</code><code class="n">ruby</code><code class="o">-</code><code class="mi">18</code><code class="o">/</code>
<code class="k">def</code> <code class="nf">define_method_taking_block</code><code class="p">(</code><code class="nb">name</code><code class="p">,</code> <code class="o">&amp;</code><code class="n">method_body_proc</code><code class="p">)</code>
<code class="nb">self</code><code class="o">.</code><code class="n">class</code><code class="o">.</code><code class="n">send</code> <code class="ss">:define_method</code><code class="p">,</code> <code class="s2">"__quirky_bird_helper_</code><code class="si">#{</code><code class="nb">name</code><code class="si">}</code><code class="s2">__"</code><code class="p">,</code> <code class="n">method_</code><code class="p">\</code>
<code class="n">body_proc</code>
<code class="nb">eval</code> <code class="o">&lt;&lt;-</code><code class="no">EOM</code>
<code class="sh"> def #{name}(a_value, &amp;a_proc)</code>
<code class="sh"> __quirky_bird_helper_#{name}__(a_value, a_proc)</code>
<code class="sh"> end</code>
<code class="no"> EOM</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nf">quirky_bird_extend</code><code class="p">(</code><code class="nb">name</code><code class="p">,</code> <code class="o">&amp;</code><code class="n">value_proc</code><code class="p">)</code>
<code class="no">Object</code><code class="o">.</code><code class="n">send</code><code class="p">(</code><code class="ss">:define_method</code><code class="p">,</code> <code class="nb">name</code><code class="p">)</code> <code class="k">do</code>
<code class="n">value_proc</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
</pre></div>
<hr /></div>
<div class="code-block">
<p class="codeblock-title">quirky_songs.rb</p>
<hr /><div class="highlight"><pre><code class="c1"># The MIT License</code>
<code class="c1"># </code>
<code class="c1"># All contents Copyright (c) 2004-2008 Reginald Braithwaite</code>
<code class="c1"># &lt;http://braythwayt.com&gt; except as otherwise noted.</code>
<code class="c1"># </code>
<code class="c1"># Permission is hereby granted, free of charge, to any person obtaining a c\</code>
<code class="n">opy</code>
<code class="c1"># of this software and associated documentation files (the "Software"), to \</code>
<code class="n">deal</code>
<code class="c1"># in the Software without restriction, including without limitation the rig\</code>
<code class="n">hts</code>
<code class="c1"># to use, copy, modify, merge, publish, distribute, sublicense, and/or sell</code>
<code class="c1"># copies of the Software, and to permit persons to whom the Software is</code>
<code class="c1"># furnished to do so, subject to the following conditions:</code>
<code class="c1"># </code>
<code class="c1"># The above copyright notice and this permission notice shall be included i\</code>
<code class="n">n</code>
<code class="c1"># all copies or substantial portions of the Software.</code>
<code class="c1"># </code>
<code class="c1"># THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS O\</code>
<code class="n">R</code>
<code class="c1"># IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</code>
<code class="c1"># FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL T\</code>
<code class="no">HE</code>
<code class="c1"># AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</code>
<code class="c1"># LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING F\</code>
<code class="no">ROM</code><code class="p">,</code>
<code class="c1"># OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN</code>
<code class="c1"># THE SOFTWARE.</code>
<code class="c1"># </code>
<code class="c1"># http://www.opensource.org/licenses/mit-license.php</code>
<code class="nb">require</code> <code class="s1">'quirky_bird'</code>
<code class="nb">require</code> <code class="s1">'blank_slate'</code>
<code class="nb">require</code> <code class="s1">'returning'</code>
<code class="n">quirky_bird_extend</code><code class="p">(</code><code class="ss">:maybe</code><code class="p">)</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">value</code><code class="o">.</code><code class="n">nil?</code>
<code class="n">returning</code><code class="p">(</code><code class="no">BlankSlate</code><code class="o">.</code><code class="n">new</code><code class="p">)</code> <code class="k">do</code> <code class="o">|</code><code class="n">it</code><code class="o">|</code>
<code class="k">def</code> <code class="nc">it</code><code class="o">.</code><code class="nf">method_missing</code><code class="p">(</code><code class="o">*</code><code class="n">args</code><code class="p">)</code>
<code class="kp">nil</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">else</code>
<code class="n">value</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="n">quirky_bird_extend</code><code class="p">(</code><code class="ss">:try</code><code class="p">)</code> <code class="k">do</code> <code class="o">|</code><code class="n">value</code><code class="o">|</code>
<code class="n">returning</code><code class="p">(</code><code class="no">BlankSlate</code><code class="o">.</code><code class="n">new</code><code class="p">)</code> <code class="k">do</code> <code class="o">|</code><code class="n">it</code><code class="o">|</code>
<code class="k">def</code> <code class="nc">it</code><code class="o">.</code><code class="nf">__value__</code><code class="o">=</code><code class="p">(</code><code class="n">arg</code><code class="p">)</code>
<code class="vi">@value</code> <code class="o">=</code> <code class="n">arg</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nc">it</code><code class="o">.</code><code class="nf">method_missing</code><code class="p">(</code><code class="nb">name</code><code class="p">,</code> <code class="o">*</code><code class="n">args</code><code class="p">)</code>
<code class="k">if</code> <code class="vi">@value</code><code class="o">.</code><code class="n">respond_to?</code><code class="p">(</code><code class="nb">name</code><code class="p">)</code>
<code class="vi">@value</code><code class="o">.</code><code class="n">send</code><code class="p">(</code><code class="nb">name</code><code class="p">,</code> <code class="o">*</code><code class="n">args</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="n">it</code><code class="o">.</code><code class="n">__value__</code> <code class="o">=</code> <code class="n">value</code>
<code class="k">end</code>
<code class="k">end</code>
</pre></div>
<hr /></div>
<h3 section-num="13.5" id="bluebirds"><span class="section-number">13.5 </span>bluebirds</h3>
<div class="code-block">
<p class="codeblock-title">before_and_after_advice.rb</p>
<hr /><div class="highlight"><pre><code class="c1"># This code contains ideas snarfed from:</code>
<code class="c1">#</code>
<code class="c1"># http://github.com/up_the_irons/immutable/tree/master</code>
<code class="c1"># http://blog.jayfields.com/2006/12/ruby-alias-method-alternative.html</code>
<code class="c1"># http://eigenclass.org/hiki.rb?bounded+space+instance_exec</code>
<code class="c1">#</code>
<code class="c1"># And a heaping side of http://blog.grayproductions.net/articles/all_about_\</code>
<code class="n">struct</code>
<code class="k">module</code> <code class="nn">BeforeAndAfterAdvice</code>
<code class="c1"># Random ID changed at each interpreter load</code>
<code class="no">UNIQ</code> <code class="o">=</code> <code class="s2">"_</code><code class="si">#{</code><code class="nb">object_id</code><code class="si">}</code><code class="s2">"</code>
<code class="no">Compositions</code> <code class="o">=</code> <code class="no">Struct</code><code class="o">.</code><code class="n">new</code><code class="p">(</code><code class="ss">:before</code><code class="p">,</code> <code class="ss">:between</code><code class="p">,</code> <code class="ss">:after</code><code class="p">)</code>
<code class="k">module</code> <code class="nn">MethodAdvice</code><code class="p">;</code> <code class="k">end</code>
<code class="k">module</code> <code class="nn">ClassMethods</code>
<code class="c1"># Example:</code>
<code class="c1">#</code>
<code class="c1"># before :foo, :bar do</code>
<code class="c1"># # ...</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># This executes the body of the block before the #foo and #bar instance\</code>
<code class="nb">methods</code>
<code class="c1"># for side effects without modifying the parameters (if any) passed to \</code>
<code class="c1">#foo</code>
<code class="c1"># and #bar</code>
<code class="c1">#</code>
<code class="c1"># before :fizz, :buzz do |p1, p2|</code>
<code class="c1"># # ...</code>
<code class="c1"># [p1, p2]</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># This executes the body of the block before the #foo and #bar instance\</code>
<code class="nb">methods</code>
<code class="c1"># for side efects, AND determines what is passed along as parameters. I\</code>
<code class="n">f</code> <code class="n">the</code> <code class="n">block</code>
<code class="c1"># takes parameters, it acts as a filter, transforming the parameters.</code>
<code class="c1">#</code>
<code class="c1"># It is possible to chain #before advice, and you can add more advice i\</code>
<code class="n">n</code> <code class="n">subclasses</code><code class="p">:</code>
<code class="c1">#</code>
<code class="c1"># class Foo</code>
<code class="c1"># def foo(bar); end</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># class Bar &lt; Foo</code>
<code class="c1"># include MethodAdvice</code>
<code class="c1">#</code>
<code class="c1"># before :foo do</code>
<code class="c1"># # ...</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># class Blitz &lt; Bar</code>
<code class="c1"># include MethodAdvice</code>
<code class="c1">#</code>
<code class="c1"># before :foo do |bar|</code>
<code class="c1"># # ...</code>
<code class="c1"># bar</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="k">def</code> <code class="nf">before</code><code class="p">(</code><code class="o">*</code><code class="n">method_symbols</code><code class="p">,</code> <code class="o">&amp;</code><code class="n">block</code><code class="p">)</code>
<code class="n">options</code> <code class="o">=</code> <code class="n">method_symbols</code><code class="o">[-</code><code class="mi">1</code><code class="o">].</code><code class="n">kind_of?</code><code class="p">(</code><code class="no">Hash</code><code class="p">)</code> <code class="p">?</code> <code class="n">method_symbols</code><code class="o">.</code><code class="n">pop</code> <code class="p">:</code> <code class="p">{}</code>
<code class="n">method_symbols</code><code class="o">.</code><code class="n">each</code> <code class="k">do</code> <code class="o">|</code><code class="n">method_sym</code><code class="o">|</code>
<code class="n">__composed_methods__</code><code class="o">[</code><code class="n">method_sym</code><code class="o">].</code><code class="n">before</code><code class="o">.</code><code class="n">unshift</code><code class="p">(</code><code class="n">__unbound_method__</code><code class="p">(\</code>
<code class="n">block</code><code class="p">,</code> <code class="n">options</code><code class="o">[</code><code class="ss">:name</code><code class="o">]</code><code class="p">))</code>
<code class="n">__rebuild_method__</code><code class="p">(</code><code class="n">method_sym</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="c1"># Example:</code>
<code class="c1">#</code>
<code class="c1"># after :foo, :bar do</code>
<code class="c1"># # ...</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># This executes the body of the block after the #foo and #bar instance \</code>
<code class="nb">methods</code>
<code class="c1"># for side effects without modifying the return values of the #foo and \</code>
<code class="c1">#bar methods</code>
<code class="c1">#</code>
<code class="c1"># after :fizz, :buzz do |r|</code>
<code class="c1"># # ...</code>
<code class="c1"># r</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># This executes the body of the block after the #foo and #bar instance \</code>
<code class="nb">methods</code>
<code class="c1"># for side efects, AND determines what is returned from the call. If th\</code>
<code class="n">e</code> <code class="n">block</code>
<code class="c1"># takes parameters, it acts as a filter, transforming the return value.</code>
<code class="c1">#</code>
<code class="c1"># It is possible to chain #after advice, and you can add more advice in\</code>
<code class="n">subclasses</code><code class="p">:</code>
<code class="c1">#</code>
<code class="c1"># class Foo</code>
<code class="c1"># def foo(bar); end</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># class Bar &lt; Foo</code>
<code class="c1"># include MethodAdvice</code>
<code class="c1">#</code>
<code class="c1"># after :foo do</code>
<code class="c1"># # ...</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># class Blitz &lt; Bar</code>
<code class="c1"># include MethodAdvice</code>
<code class="c1">#</code>
<code class="c1"># after :foo do |r|</code>
<code class="c1"># # ...</code>
<code class="c1"># r</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="k">def</code> <code class="nf">after</code><code class="p">(</code><code class="o">*</code><code class="n">method_symbols</code><code class="p">,</code> <code class="o">&amp;</code><code class="n">block</code><code class="p">)</code>
<code class="n">options</code> <code class="o">=</code> <code class="n">method_symbols</code><code class="o">[-</code><code class="mi">1</code><code class="o">].</code><code class="n">kind_of?</code><code class="p">(</code><code class="no">Hash</code><code class="p">)</code> <code class="p">?</code> <code class="n">method_symbols</code><code class="o">.</code><code class="n">pop</code> <code class="p">:</code> <code class="p">{}</code>
<code class="n">method_symbols</code><code class="o">.</code><code class="n">each</code> <code class="k">do</code> <code class="o">|</code><code class="n">method_sym</code><code class="o">|</code>
<code class="n">__composed_methods__</code><code class="o">[</code><code class="n">method_sym</code><code class="o">].</code><code class="n">after</code><code class="o">.</code><code class="n">push</code><code class="p">(</code><code class="n">__unbound_method__</code><code class="p">(</code><code class="n">bloc</code><code class="p">\</code>
<code class="n">k</code><code class="p">,</code> <code class="n">options</code><code class="o">[</code><code class="ss">:name</code><code class="o">]</code><code class="p">))</code>
<code class="n">__rebuild_method__</code><code class="p">(</code><code class="n">method_sym</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="c1"># Removes all advice from the named methods. Intended for testing.</code>
<code class="c1">#</code>
<code class="k">def</code> <code class="nf">reset_befores_and_afters</code><code class="p">(</code><code class="o">*</code><code class="n">method_symbols</code><code class="p">)</code>
<code class="n">method_symbols</code><code class="o">.</code><code class="n">each</code> <code class="k">do</code> <code class="o">|</code><code class="n">method_sym</code><code class="o">|</code>
<code class="n">__composed_methods__</code><code class="o">[</code><code class="n">method_sym</code><code class="o">].</code><code class="n">before</code> <code class="o">=</code> <code class="o">[]</code>
<code class="n">__composed_methods__</code><code class="o">[</code><code class="n">method_sym</code><code class="o">].</code><code class="n">after</code> <code class="o">=</code> <code class="o">[]</code>
<code class="n">__rebuild_method__</code><code class="p">(</code><code class="n">method_sym</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="c1"># Modified to re-apply advice when a method is overridden. So:</code>
<code class="c1">#</code>
<code class="c1"># class Foo</code>
<code class="c1"># def foo(bar); end</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># class Bar &lt; Foo</code>
<code class="c1"># include MethodAdvice</code>
<code class="c1">#</code>
<code class="c1"># after :foo do</code>
<code class="c1"># # ...</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># class Blitz &lt; Bar</code>
<code class="c1"># include MethodAdvice</code>
<code class="c1">#</code>
<code class="c1"># def foo(bar)</code>
<code class="c1"># # ...</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># end</code>
<code class="c1">#</code>
<code class="c1"># In this case the class Blitz overrides the method #foo, but the advic\</code>
<code class="n">e</code> <code class="k">in</code>
<code class="c1"># class Bar is still applied, the override happens ONLY on the inner me\</code>
<code class="n">thod</code><code class="p">,</code>
<code class="c1"># not the advice.</code>
<code class="c1">#</code>
<code class="c1"># Note well that super has undefined behaviour in this situation.</code>
<code class="c1">#</code>
<code class="k">def</code> <code class="nf">method_added</code><code class="p">(</code><code class="n">method_sym</code><code class="p">)</code>
<code class="k">unless</code> <code class="nb">instance_variable_get</code><code class="p">(</code><code class="s2">"@</code><code class="si">#{</code><code class="no">UNIQ</code><code class="si">}</code><code class="s2">_in_method_added"</code><code class="p">)</code>
<code class="n">__safely__</code> <code class="k">do</code>
<code class="n">__composed_methods__</code><code class="o">[</code><code class="n">method_sym</code><code class="o">].</code><code class="n">between</code> <code class="o">=</code> <code class="nb">self</code><code class="o">.</code><code class="n">instance_method</code><code class="p">(</code><code class="n">m</code><code class="p">\</code>
<code class="n">ethod_sym</code><code class="p">)</code>
<code class="vi">@old_method_added</code> <code class="ow">and</code> <code class="vi">@old_method_added</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">method_sym</code><code class="p">)</code>
<code class="n">__rebuild_method__</code><code class="p">(</code><code class="n">method_sym</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nf">__composed_methods__</code>
<code class="n">ancestral_composer</code> <code class="o">=</code> <code class="nb">ancestors</code><code class="o">.</code><code class="n">detect</code> <code class="p">{</code> <code class="o">|</code><code class="n">ancestor</code><code class="o">|</code> <code class="n">ancestor</code><code class="o">.</code><code class="n">instance_</code><code class="p">\</code>
<code class="n">variable_defined?</code><code class="p">(</code><code class="ss">:@__composed_methods__</code><code class="p">)</code> <code class="p">}</code>
<code class="k">if</code> <code class="n">ancestral_composer</code>
<code class="n">ancestral_composer</code><code class="o">.</code><code class="n">instance_variable_get</code><code class="p">(</code><code class="ss">:@__composed_methods__</code><code class="p">)</code>
<code class="k">else</code>
<code class="vi">@__composed_methods__</code> <code class="o">||=</code> <code class="no">Hash</code><code class="o">.</code><code class="n">new</code> <code class="p">{</code> <code class="o">|</code><code class="nb">hash</code><code class="p">,</code> <code class="n">method_sym</code><code class="o">|</code> <code class="nb">hash</code><code class="o">[</code><code class="nb">method</code><code class="p">\</code>
<code class="n">_sym</code><code class="o">]</code> <code class="o">=</code> <code class="no">BeforeAndAfterAdvice</code><code class="o">::</code><code class="no">Compositions</code><code class="o">.</code><code class="n">new</code><code class="p">(</code><code class="o">[]</code><code class="p">,</code> <code class="nb">self</code><code class="o">.</code><code class="n">instance_method</code><code class="p">(</code><code class="n">met</code><code class="p">\</code>
<code class="n">hod_sym</code><code class="p">),</code> <code class="o">[]</code><code class="p">)</code> <code class="p">}</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nf">__rebuild_without_advice__</code><code class="p">(</code><code class="n">method_sym</code><code class="p">,</code> <code class="n">old_method</code><code class="p">)</code>
<code class="k">if</code> <code class="n">old_method</code><code class="o">.</code><code class="n">arity</code> <code class="o">==</code> <code class="mi">0</code>
<code class="n">define_method</code><code class="p">(</code><code class="n">method_sym</code><code class="p">)</code> <code class="p">{</code> <code class="n">old_method</code><code class="o">.</code><code class="n">bind</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code><code class="o">.</code><code class="n">call</code> <code class="p">}</code>
<code class="k">else</code>
<code class="n">define_method</code><code class="p">(</code><code class="n">method_sym</code><code class="p">)</code> <code class="p">{</code> <code class="o">|*</code><code class="n">params</code><code class="o">|</code> <code class="n">old_method</code><code class="o">.</code><code class="n">bind</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="o">*</code><code class="nb">p</code><code class="p">\</code>
<code class="n">arams</code><code class="p">)</code> <code class="p">}</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nf">__rebuild_advising_no_parameters__</code><code class="p">(</code><code class="n">method_sym</code><code class="p">,</code> <code class="n">old_method</code><code class="p">,</code> <code class="n">befores</code><code class="p">,\</code>
<code class="n">afters</code><code class="p">)</code>
<code class="n">define_method</code><code class="p">(</code><code class="n">method_sym</code><code class="p">)</code> <code class="k">do</code>
<code class="n">befores</code><code class="o">.</code><code class="n">each</code> <code class="k">do</code> <code class="o">|</code><code class="n">before_advice_method</code><code class="o">|</code>
<code class="n">before_advice_method</code><code class="o">.</code><code class="n">bind</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code><code class="o">.</code><code class="n">call</code>
<code class="k">end</code>
<code class="n">afters</code><code class="o">.</code><code class="n">inject</code><code class="p">(</code><code class="n">old_method</code><code class="o">.</code><code class="n">bind</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code><code class="o">.</code><code class="n">call</code><code class="p">)</code> <code class="k">do</code> <code class="o">|</code><code class="n">ret_val</code><code class="p">,</code> <code class="n">after_advice</code><code class="p">\</code>
<code class="n">_method</code><code class="o">|</code>
<code class="n">after_advice_method</code><code class="o">.</code><code class="n">bind</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code><code class="o">.</code><code class="n">call</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nf">__rebuild_advising_with_parameters__</code><code class="p">(</code><code class="n">method_sym</code><code class="p">,</code> <code class="n">old_method</code><code class="p">,</code> <code class="n">before</code><code class="p">\</code>
<code class="n">s</code><code class="p">,</code> <code class="n">afters</code><code class="p">)</code>
<code class="n">define_method</code><code class="p">(</code><code class="n">method_sym</code><code class="p">)</code> <code class="k">do</code> <code class="o">|*</code><code class="n">params</code><code class="o">|</code>
<code class="n">afters</code><code class="o">.</code><code class="n">inject</code><code class="p">(</code>
<code class="n">old_method</code><code class="o">.</code><code class="n">bind</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code><code class="o">.</code><code class="n">call</code><code class="p">(</code>
<code class="o">*</code><code class="n">befores</code><code class="o">.</code><code class="n">inject</code><code class="p">(</code><code class="n">params</code><code class="p">)</code> <code class="k">do</code> <code class="o">|</code><code class="n">acc_params</code><code class="p">,</code> <code class="n">before_advice_method</code><code class="o">|</code>
<code class="k">if</code> <code class="n">before_advice_method</code><code class="o">.</code><code class="n">arity</code> <code class="o">==</code> <code class="mi">0</code>
<code class="n">before_advice_method</code><code class="o">.</code><code class="n">bind</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code><code class="o">.</code><code class="n">call</code>
<code class="n">acc_params</code>
<code class="k">else</code>
<code class="n">before_advice_method</code><code class="o">.</code><code class="n">bind</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="o">*</code><code class="n">acc_params</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="p">)</code>
<code class="p">)</code> <code class="k">do</code> <code class="o">|</code><code class="n">ret_val</code><code class="p">,</code> <code class="n">after_advice_method</code><code class="o">|</code>
<code class="k">if</code> <code class="n">after_advice_method</code><code class="o">.</code><code class="n">arity</code> <code class="o">==</code> <code class="mi">0</code>
<code class="n">after_advice_method</code><code class="o">.</code><code class="n">bind</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code><code class="o">.</code><code class="n">call</code>
<code class="n">ret_val</code>
<code class="k">else</code>
<code class="n">after_advice_method</code><code class="o">.</code><code class="n">bind</code><code class="p">(</code><code class="nb">self</code><code class="p">)</code><code class="o">.</code><code class="n">call</code><code class="p">(</code><code class="n">ret_val</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nf">__rebuild_method__</code><code class="p">(</code><code class="n">method_sym</code><code class="p">)</code>
<code class="n">__safely__</code> <code class="k">do</code>
<code class="n">composition</code> <code class="o">=</code> <code class="n">__composed_methods__</code><code class="o">[</code><code class="n">method_sym</code><code class="o">]</code>
<code class="n">old_method</code> <code class="o">=</code> <code class="n">composition</code><code class="o">.</code><code class="n">between</code>
<code class="k">if</code> <code class="n">composition</code><code class="o">.</code><code class="n">before</code><code class="o">.</code><code class="n">empty?</code> <code class="ow">and</code> <code class="n">composition</code><code class="o">.</code><code class="n">after</code><code class="o">.</code><code class="n">empty?</code>
<code class="n">__rebuild_without_advice__</code><code class="p">(</code><code class="n">method_sym</code><code class="p">,</code> <code class="n">old_method</code><code class="p">)</code>
<code class="k">else</code>
<code class="n">arity</code> <code class="o">=</code> <code class="n">old_method</code><code class="o">.</code><code class="n">arity</code>
<code class="k">if</code> <code class="n">old_method</code><code class="o">.</code><code class="n">arity</code> <code class="o">==</code> <code class="mi">0</code>
<code class="n">__rebuild_advising_no_parameters__</code><code class="p">(</code><code class="n">method_sym</code><code class="p">,</code> <code class="n">old_method</code><code class="p">,</code> <code class="n">comp</code><code class="p">\</code>
<code class="n">osition</code><code class="o">.</code><code class="n">before</code><code class="p">,</code> <code class="n">composition</code><code class="o">.</code><code class="n">after</code><code class="p">)</code>
<code class="k">else</code>
<code class="n">__rebuild_advising_with_parameters__</code><code class="p">(</code><code class="n">method_sym</code><code class="p">,</code> <code class="n">old_method</code><code class="p">,</code> <code class="n">co</code><code class="p">\</code>
<code class="n">mposition</code><code class="o">.</code><code class="n">before</code><code class="p">,</code> <code class="n">composition</code><code class="o">.</code><code class="n">after</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nf">__safely__</code>
<code class="n">was</code> <code class="o">=</code> <code class="nb">instance_variable_get</code><code class="p">(</code><code class="s2">"@</code><code class="si">#{</code><code class="no">UNIQ</code><code class="si">}</code><code class="s2">_in_method_added"</code><code class="p">)</code>
<code class="k">begin</code>
<code class="nb">instance_variable_set</code><code class="p">(</code><code class="s2">"@</code><code class="si">#{</code><code class="no">UNIQ</code><code class="si">}</code><code class="s2">_in_method_added"</code><code class="p">,</code> <code class="kp">true</code><code class="p">)</code>
<code class="k">yield</code>
<code class="k">ensure</code>
<code class="nb">instance_variable_set</code><code class="p">(</code><code class="s2">"@</code><code class="si">#{</code><code class="no">UNIQ</code><code class="si">}</code><code class="s2">_in_method_added"</code><code class="p">,</code> <code class="n">was</code><code class="p">)</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nf">__unbound_method__</code><code class="p">(</code><code class="n">a_proc</code><code class="p">,</code> <code class="n">name_prefx</code> <code class="o">=</code> <code class="kp">nil</code><code class="p">)</code>
<code class="k">begin</code>
<code class="n">old_critical</code><code class="p">,</code> <code class="no">Thread</code><code class="o">.</code><code class="n">critical</code> <code class="o">=</code> <code class="no">Thread</code><code class="o">.</code><code class="n">critical</code><code class="p">,</code> <code class="kp">true</code>
<code class="n">n</code> <code class="o">=</code> <code class="mi">0</code>
<code class="n">n</code> <code class="o">+=</code> <code class="mi">1</code> <code class="k">while</code> <code class="nb">respond_to?</code><code class="p">(</code><code class="n">mname</code><code class="o">=</code><code class="s2">"</code><code class="si">#{</code><code class="n">name_prefx</code> <code class="o">||</code> <code class="s1">'__method_advice'</code><code class="si">}</code><code class="s2">_\</code>
<code class="si">#{</code><code class="n">n</code><code class="si">}</code><code class="s2">"</code><code class="p">)</code>
<code class="no">MethodAdvice</code><code class="o">.</code><code class="n">module_eval</code><code class="p">{</code> <code class="n">define_method</code><code class="p">(</code><code class="n">mname</code><code class="p">,</code> <code class="o">&amp;</code><code class="n">a_proc</code><code class="p">)</code> <code class="p">}</code>
<code class="k">ensure</code>
<code class="no">Thread</code><code class="o">.</code><code class="n">critical</code> <code class="o">=</code> <code class="n">old_critical</code>
<code class="k">end</code>
<code class="k">begin</code>
<code class="no">MethodAdvice</code><code class="o">.</code><code class="n">instance_method</code><code class="p">(</code><code class="n">mname</code><code class="p">)</code>
<code class="k">ensure</code>
<code class="no">MethodAdvice</code><code class="o">.</code><code class="n">module_eval</code><code class="p">{</code> <code class="n">remove_method</code><code class="p">(</code><code class="n">mname</code><code class="p">)</code> <code class="p">}</code> <code class="k">unless</code> <code class="n">name_prefx</code> <code class="p">\</code>
<code class="k">rescue</code> <code class="kp">nil</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">end</code>
<code class="k">def</code> <code class="nc">self</code><code class="o">.</code><code class="nf">included</code><code class="p">(</code><code class="n">receiver</code><code class="p">)</code>
<code class="n">receiver</code><code class="o">.</code><code class="n">extend</code> <code class="no">ClassMethods</code>
<code class="n">receiver</code><code class="o">.</code><code class="n">send</code> <code class="ss">:include</code><code class="p">,</code> <code class="no">MethodAdvice</code>
<code class="n">receiver</code><code class="o">.</code><code class="n">instance_variable_set</code><code class="p">(</code><code class="s2">"@</code><code class="si">#{</code><code class="no">UNIQ</code><code class="si">}</code><code class="s2">_in_method_added"</code><code class="p">,</code> <code class="kp">false</code><code class="p">)</code>
<code class="n">receiver</code><code class="o">.</code><code class="n">instance_variable_set</code><code class="p">(</code><code class="ss">:@old_method_added</code><code class="p">,</code> <code class="n">receiver</code><code class="o">.</code><code class="n">public_meth</code><code class="p">\</code>
<code class="n">od_defined?</code><code class="p">(</code><code class="ss">:method_added</code><code class="p">)</code> <code class="o">&amp;&amp;</code> <code class="n">receiver</code><code class="o">.</code><code class="n">instance_method</code><code class="p">(</code><code class="ss">:method_added</code><code class="p">))</code>
<code class="k">end</code>
<code class="k">end</code>
</pre></div>
<hr /></div>
</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>