For years a tiny code style issue has bothered me in Ruby. I find myself frequently building up a set of variables and then building a Hash where the keys all match the variables. It is a small nit-pick, and never wastes much time, but it has always annoyed me. The wasted duplication to have {:some_key => some_key}
for a long list of variables, when the key and the variable are named the same. Convention over configuration and all that. Ruby is a beautiful and flexible language. Why can’t we make it simpler and cleaner to create a Hash based of some locally defined variables. It turns out more complicated than one would think, because of trying to bind to the current variable scope.
In the end what I wanted was a way to create a hash that would looks something like this, which I like to call a SelfReferringHash
###Inspiring a solution
I mentioned this annoyance years ago to Ara Howard, and he whipped up a example very quickly, but it didn’t feel quite right. Ara proposed a few iterations with various syntax’s :result.to_h{}
or [:a, :b, :c].to_h{}
but the syntax was distracting. So I kind of forgot about the issue and forgot about the issue for awhile.
I then recently came across this post Playing Around with Ruby Hashes. Where Alex wants to add various features such as setting a arbitrarily deep value on the Hash without all the intermediate checks and creation of empty hashes
The post build some fun features onto Ruby’s Hash and the post inspired me to play around with building a cleaner solution.
###Attempting a solution
While one of Ara’s symbol to hash solutions was pretty close to what I wanted, it Monkey patched the Array and and Symbol I wanted to avoid that. I decided that I should make a new object and subclass Hash opposed to tacking my code onto any existing objects in the system.
Running that code results in the following output, with the SuperHash.new([:calculation, :word, :data]){}
ending up being the ‘cleanest’ way to invoke the code.
In the end, this might be interesting if I had some other things to patch onto the Hash object. Unfortunately it seems like this still isn’t really that useful and it is a bit to awkward. I could never avoid the primary issue I had with Ara’s examples of having to awkwardly pass the context. All solutions seem to require you to pass a empty block to be able to bind to the context and access the variables at that time. Having a initializer or a class method which requires {}
just seems to awkward to be useable. So after all this time I am still left feeling, unsatisfied. While this is a very simple problem to understand and Ruby is a very flexible language. The issues of binding to a context and variable scoping makes building a more beautiful and usable version of a self referring Hash out of my reach.
If anyone has suggestions or ideas on how to build something that is a bit cleaner or closer to my goal and doesn’t resort to passing a empty block, I would love to see any other solutions. Perhaps, I am missing some more interesting way to bend Ruby to fit my mind.