tag:www.rhnh.net,2008:/lambda Lambda - Xavier Shay's Blog 2008-11-03T08:54:09Z Enki Xavier Shay notreal@rhnh.net tag:www.rhnh.net,2008:Post/787 2008-11-03T08:54:00Z 2008-11-03T08:54:09Z Comparing lambdas in ruby <p><code>to_ruby</code> is a really convenient way to compare the equality of two lambdas. It&#8217;s a bit slow though. If we get our hands dirty (only a little!) with ParseTree, we can get a result 2 orders of magnitude quicker. I&#8217;d be interested to see if these benchmarks differ significantly on other versions of ruby.</p><table class="CodeRay"><tr> <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt> </tt>2<tt> </tt></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">~ $ ruby -v<tt> </tt>ruby 1.8.6 (2007-09-23 patchlevel 110) [i686-darwin8.11.1]<tt> </tt></pre></td> </tr></table> <table class="CodeRay"><tr> <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt> </tt>2<tt> </tt>3<tt> </tt>4<tt> </tt>5<tt> </tt>6<tt> </tt>7<tt> </tt>8<tt> </tt>9<tt> </tt><strong>10</strong><tt> </tt>11<tt> </tt>12<tt> </tt>13<tt> </tt>14<tt> </tt>15<tt> </tt>16<tt> </tt>17<tt> </tt>18<tt> </tt>19<tt> </tt><strong>20</strong><tt> </tt>21<tt> </tt>22<tt> </tt>23<tt> </tt>24<tt> </tt>25<tt> </tt>26<tt> </tt></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">require <span class="s"><span class="dl">'</span><span class="k">benchmark</span><span class="dl">'</span></span><tt> </tt>require <span class="s"><span class="dl">'</span><span class="k">parse_tree</span><span class="dl">'</span></span><tt> </tt>require <span class="s"><span class="dl">'</span><span class="k">ruby2ruby</span><span class="dl">'</span></span><tt> </tt><tt> </tt><span class="r">def</span> <span class="fu">gen_lambda</span><tt> </tt> lambda {|x| x + <span class="i">1</span> }<tt> </tt><span class="r">end</span><tt> </tt><tt> </tt><span class="co">Parser</span> = <span class="co">ParseTree</span>.new(<span class="pc">false</span>)<tt> </tt><tt> </tt><span class="c"># This only requires parse tree, not ruby2ruby</span><tt> </tt><span class="r">def</span> <span class="fu">proc_identity</span>(block)<tt> </tt> klass = <span class="co">Class</span>.new<tt> </tt> name = <span class="s"><span class="dl">&quot;</span><span class="k">myproc</span><span class="dl">&quot;</span></span><tt> </tt> klass.send(<span class="sy">:define_method</span>, name, &amp;block)<tt> </tt><tt> </tt> <span class="c"># .last ignores the method name and definition - they're irrelevant</span><tt> </tt> <span class="co">Parser</span>.parse_tree_for_method(klass, name).last <tt> </tt><span class="r">end</span><tt> </tt><tt> </tt>n = <span class="i">1000</span><tt> </tt><span class="co">Benchmark</span>.bmbm <span class="r">do</span> |x|<tt> </tt> x.report(<span class="s"><span class="dl">&quot;</span><span class="k">#to_ruby</span><span class="dl">&quot;</span></span>) { n.times { gen_lambda.to_ruby == gen_lambda.to_ruby }}<tt> </tt> x.report(<span class="s"><span class="dl">&quot;</span><span class="k">#to_sexp</span><span class="dl">&quot;</span></span>) { n.times { gen_lambda.to_sexp == gen_lambda.to_sexp }}<tt> </tt> x.report(<span class="s"><span class="dl">&quot;</span><span class="k">manual</span><span class="dl">&quot;</span></span>) { n.times { proc_identity(gen_lambda) == proc_identity(gen_lambda) }}<tt> </tt><span class="r">end</span><tt> </tt></pre></td> </tr></table> <table class="CodeRay"><tr> <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt> </tt>2<tt> </tt>3<tt> </tt>4<tt> </tt></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"> user system total real<tt> </tt>#to_ruby 4.460000 0.220000 4.680000 ( 4.695327)<tt> </tt>#to_sexp 0.920000 0.190000 1.110000 ( 1.110214)<tt> </tt>manual 0.030000 0.000000 0.030000 ( 0.032768)<tt> </tt></pre></td> </tr></table> <p>In case you were wondering, I was playing around with this while implementing <a href="http://github.com/xaviershay/dm-more/tree/master/dm-sweatshop">unique data generation for dm-sweatshop</a></p>