This Old Hash

The Hash may well be the most used class in Ruby. Sure, our programs have arrays and strings galore, but they generally come and go without much ado. Hashes on the other hand get *used*; and by that I mean to say, we spend a lot of time fussing with them. I think there are two significant reasons for this and I will focus on the first, and the more important of the two, here.

Now, I suspect you would agree, if I were to present you with a class which was clearly overkill for vast majority of its intended uses, and its use required repeated mitigation of its unused features, I have no doubt, you’d unequivocally advise me to select a “better tool for the job“. And yet, that’s the situation all Ruby programmers face, day in and day out, with Ruby’s Hash.

Ruby’s Hash is exceptionally powerful because it supports any type of object as a hash key. That’s really really cool… for all of about five minutes. The truth is, the vast majority of cases only require one type of key –for Ruby that will either be a Symbol or a String, and because of this, a great deal of time and code is wasted ensuring all keys are that single type. Because of this, methods like #to_sym often riddle our scripts.

The issue is undeniably attested to by real world “solutions” others have created to address it, such as Ruby Facets’ Hash#rekey. and Ruby on Rails’ HashWithIndifferentAccess. But let’s face it, these are both underwhelming attempts at mitigating the fundamental problem.

A real solution would have the current Hash class renamed, and a new limited-key structure put in its place. The old class would still be available, of course, for those special cases when a key of any object type is required, but the new, more utilitarian Hash class would be the literally-constructed default. The end effect of this change would be simple:

  h['a'] == h[:a]
  h['1'] == h[1]

This means reducing all hash keys to a single *symbolic* index type. It does not matter what the actual reference is, a String, Symbol, Integer, etc. just so long as it has a predictable symbolic representation.

It may feel a bit strange to consider a suggestion that actually calls for the reduction of features. More often change requests call for just the opposite and YAGNI has to be peddled out on them. But, I think, we often underestimate the power of simplicity. Consider ideas such as convention-over-configuration and duck-typing –simplifications that are not necessarily intuitive at first. But in the end, they make our life as programmers a good bit more productive.

“Make everything as simple as possible, but not simpler.”
–Albert Einstein