tag:www.rhnh.net,2008:/hash
Hash - Xavier Shay's Blog
2008-05-10T11:37:55Z
Enki
Xavier Shay
notreal@rhnh.net
tag:www.rhnh.net,2008:Post/779
2008-05-10T11:37:00Z
2008-05-10T11:37:55Z
Hash trumps case
<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></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># Two equivalent functions</span><tt>
</tt><span class="r">def</span> <span class="fu">rgb</span>(color)<tt>
</tt> <span class="r">case</span> color<tt>
</tt> <span class="r">when</span> <span class="sy">:red</span> <span class="r">then</span> <span class="s"><span class="dl">'</span><span class="k">ff0000</span><span class="dl">'</span></span><tt>
</tt> <span class="r">when</span> <span class="sy">:green</span> <span class="r">then</span> <span class="s"><span class="dl">'</span><span class="k">00ff00</span><span class="dl">'</span></span><tt>
</tt> <span class="r">when</span> <span class="sy">:blue</span> <span class="r">then</span> <span class="s"><span class="dl">'</span><span class="k">0000ff</span><span class="dl">'</span></span><tt>
</tt> <span class="r">else</span> <span class="s"><span class="dl">'</span><span class="k">000000</span><span class="dl">'</span></span> <span class="c"># Default to black</span><tt>
</tt> <span class="r">end</span><tt>
</tt><span class="r">end</span><tt>
</tt><tt>
</tt><span class="r">def</span> <span class="fu">rgb2</span>(color)<tt>
</tt> {<tt>
</tt> <span class="sy">:red</span> => <span class="s"><span class="dl">'</span><span class="k">ff0000</span><span class="dl">'</span></span>,<tt>
</tt> <span class="sy">:green</span> => <span class="s"><span class="dl">'</span><span class="k">00ff00</span><span class="dl">'</span></span>,<tt>
</tt> <span class="sy">:blue</span> => <span class="s"><span class="dl">'</span><span class="k">0000ff</span><span class="dl">'</span></span><tt>
</tt> }[color] || <span class="s"><span class="dl">'</span><span class="k">000000</span><span class="dl">'</span></span><tt>
</tt><span class="r">end</span><tt>
</tt></pre></td>
</tr></table>
<p>Even though these functions are equivalent, the second carries more semantic weight – it maps a symbol directly to a color. The <code>case</code> sample makes no such guarantees since you can execute any arbitrary code in the <code>then</code> block. In addition, a hash is easier to work with – you can easily iterate over the keys, extract to another method if you need reuse, or query it for other properties (for example, 3 colors are available). It is also easier to read – both aesthetically and because it contains fewer tokens. In almost all circumstances I will prefer a hash over a case statement.</p>
<p><strong>Relationships in data are easier to comprehend and manipulate than relationships in code.</strong></p>
tag:www.rhnh.net,2008:Post/234
2007-11-15T05:55:00Z
2007-11-15T06:02:33Z
Hash#translate_keys_and_values
<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></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="r">module</span> <span class="cl">CoreExtensions</span><tt>
</tt> <span class="r">module</span> <span class="cl">Hash</span> <tt>
</tt> <span class="r">def</span> <span class="fu">translate_keys_and_values</span>(&block)<tt>
</tt> inject({}) {|a, (key, value)| a.update(block.call(key) => block.call(value))}<tt>
</tt> <span class="r">end</span><tt>
</tt> <span class="r">end</span><tt>
</tt><span class="r">end</span><tt>
</tt><tt>
</tt><span class="co">Hash</span>.send(<span class="sy">:include</span>, <span class="co">CoreExtensions</span>::<span class="co">Hash</span>)<tt>
</tt></pre></td>
</tr></table>
<p>It’s like <code>symbolize_keys</code> but a bit more flexible. It calls the block for every key and value in the hash. Of course you could tune it just do keys or values if you wanted. I do not want!</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' }">{<span class="s"><span class="dl">"</span><span class="k">1</span><span class="dl">"</span></span> => <span class="s"><span class="dl">"</span><span class="k">2</span><span class="dl">"</span></span>}.translate_keys_and_values(&<span class="sy">:to_i</span>) <span class="c"># => {1 => 2}</span><tt>
</tt>{<span class="i">1</span> => <span class="i">2</span>}.translate_keys_and_values {|x| x + <span class="i">1</span> } <span class="c"># => {2 => 3}</span><tt>
</tt></pre></td>
</tr></table>
tag:www.rhnh.net,2008:Post/216
2007-11-05T23:21:00Z
2007-11-05T23:36:36Z
Facets patch
<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' }">$ svn log svn://rubyforge.org/var/svn/facets/trunk -r 383 -v<tt>
</tt>---------------------------------------------------------------------</pre></td>
</tr></table>
<p>r383 | transami | 2007-11-03 23:31:54 +1100 (Sat, 03 Nov 2007) | 2 lines
Changed paths:
M /trunk/lib/core/facets/hash/op.rb
M /trunk/test/unit/hash/test_op.rb</p>
<p>Fixed bug in Hash#- Thanks to Xavier Shay.</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>3<tt>
</tt>4<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">--- ruby<tt>
</tt>require 'facets/hash/op'<tt>
</tt>{:a => 1, :b => 2, :c => 3} - [:a, :b] # => {:c => 3}<tt>
</tt>{:a => 1, :b => 2, :c => 3} - {:a => 1, :b => 99} # => {:b => 2, :c => 3}<tt>
</tt></pre></td>
</tr></table>
<p>It may be small, but it’s authentic. In the 2.0.5 gem.</p>
tag:www.rhnh.net,2008:Post/180
2007-10-23T07:46:00Z
2007-10-23T07:48:34Z
Enumerable#inject is my favourite method
<p><em>Combines the elements of enum by applying the block to an accumulator value (memo) and each element in turn. At each step, memo is set to the value returned by the block. – <a href="http://www.ruby-doc.org/core/classes/Enumerable.html#M003171">RubyDoc</a></em></p>
<p>It just doesn’t sound very helpful. I must confess, it isn’t something I use everyday. But I love that when you do want to use it, it is oh so sweet. The canonical example is summing the elements in an array:</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></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">[<span class="i">1</span>,<span class="i">2</span>,<span class="i">3</span>].inject(<span class="i">0</span>) {|sum, n| sum + n} <span class="c"># => 6</span><tt>
</tt></pre></td>
</tr></table>
<p>Probably the most used pattern is converting an array to a hash:</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></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">[<span class="i">1</span>,<span class="i">2</span>,<span class="i">3</span>].inject({}) {|a, v| a.update(v => v * <span class="i">2</span>)} <span class="c"># => {1 => 2, 2 => 4, 3 => 6}</span><tt>
</tt></pre></td>
</tr></table>
<p>Someone in <span class="caps">IRC</span> today wanted a nested send, something like @”string”.send(“trim.downcase”)</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></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="s"><span class="dl">"</span><span class="k">trim.downcase</span><span class="dl">"</span></span>.split(<span class="s"><span class="dl">'</span><span class="k">.</span><span class="dl">'</span></span>).inject(<span class="s"><span class="dl">"</span><span class="k">HELLO </span><span class="dl">"</span></span>) {|obj, method| obj.send(method)} <span class="c"># => "hello"</span><tt>
</tt></pre></td>
</tr></table>
<p>What do you inject?</p>
tag:www.rhnh.net,2008:Post/125
2007-07-26T07:17:00Z
2007-08-15T07:26:16Z
This is stupid: Hash#select vs reject
<p>A little consistency would be nice…</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' }">{<span class="i">1</span>=><span class="i">1</span>, <span class="i">2</span>=><span class="i">2</span>, <span class="i">3</span>=><span class="i">3</span>}.reject {|key, value| key != <span class="i">1</span> } <span class="c"># => {1=>1}</span><tt>
</tt>{<span class="i">1</span>=><span class="i">1</span>, <span class="i">2</span>=><span class="i">2</span>, <span class="i">3</span>=><span class="i">3</span>}.select {|key, value| key == <span class="i">1</span> } <span class="c"># => [[1, 1]]</span><tt>
</tt></pre></td>
</tr></table>