# Abusing Ruby Hashes for fun

### Oinak ・2 min read

Every Ruby developer loves their hashes, they are available in the core, O(1) (which means *fast*) for access, and they include the awesomest module in the world: Enumerable.

The fact, however that we are used to utilise the as mere dictionaries, or handy data aggregations whenever we can't be bothered to create a custom class.

That means that we usually only put `"strings"`

or `:symbols`

as keys. but hash keys are not limited to that, you can use anything that responds to `.hash`

method, and that in ruby is *almost everything*.

So thinking about this I came around to try to test the limits of this idea:

Basic usage of hash, with booleans as keys:

```
>> h = {true => '1 is odd', false => '1 is even'}
=> {true => "1 is odd", false => "1 is even"}
>> h[true]
=> "1 is odd"
```

Let's calculate the keys instead of using literal values

```
>> h = {1.odd? => '1 is odd', 1.even? => '1 is even' }
=> {true=>"1 is odd", false=>"1 is even"}
>> h[true]
=> "1 is odd"
```

Let's change `1.odd?`

for `p.odd?`

so that it can be defined dynamically:

```
>> p = 1; h = { p.odd? => "#{p} is odd", p.even? => "#{p} is even" }
=> {true=>"1 is odd", false=>"1 is even"}
>> h[true]
=> "1 is odd"
>> p = 0; h = { p.odd? => "#{p} is odd", p.even? => "#{p} is even" }
=> {false=>"0 is odd", true=>"0 is even"}
>> h[true]
=> "0 is even"
```

But that only works defining `p`

before `h`

, so let's go one step further:

```
>> f = -> (p) { { p.odd? => 'odd', p.even? => 'even' }[true] }
=> #<Proc:0x00000002052bf0@(irb):49 (lambda)>
>> f[1]
=> "odd"
>> f[0]
=> "even"
```

And now, what if the procs from the keys could be more complex predicates, like *nested procs*:

```
>> f = -> (p) { { ->(a) { a.odd? }[p] => 'odd', ->(a) { a.even? }[p] => 'even' }[true] }
=> #<Proc:0x0000563ce10524d0@(irb):10 (lambda)>
>> f[1]
=> "odd"
>> f[2]
=> "even"
```

Are you dizzy about the braces? Let's put this some othe way:

```
>> f = proc do |p|
Hash.new.merge(
proc { |a| a.odd? }.call(p) => 'odd',
proc { |b| b.even? }.call(p) => 'even'
).fetch(true)
end
=> #<Proc:0x00000001fac070@(irb):52 (lambda)>
>> f[1]
=> "odd"
>> f[2]
=> "even"
```

You may as well tell me that this is a very convoluted way to tell the oddness of a number, but odd and even are here only to not distract from the explanation, the fact is that you can replace `proc { |a| a.odd? }`

for anything that accepts `.call`

with the appropriate parameters and have a very lean classifier for any disjoint discreet set.

This is not necessarily the best way to do this, you might rather use a case/when statement. But at least I hope you can leave today with a broader idea of ruby hashes and what can go on their keys.

P.S: salutations to @tholford0 who *suffered* this with no explanations as a whiteboard brain-teaser. (not an interview)

Thank you for the shout-out, @oinak . And nice write up! You consistently blow my mind with your arcane knowledge of Ruby :)