[] must be renamed
Here is the proposal for Ruby 4.
Hash#[] and Array#[] have to be renamed to something that is less convenient to
use. For example, to Hash#get and Array#get. These methods should either
accept 2 parameters (a key/index and a default value), or one parameter
(key/index) and a block which evaluates the default value.
Hash#fetch and Array#fetch have to be renamed to Hash#[] and Array#[].
In other words, {Hash,Array}#[] should fail when an element is missing.
Returning nil by default is an anti-pattern and should be avoided.
But until Ruby 4 is there, we have to be deal with what we have. The simplicity
of calling #[] leads to code that is harder to debug in case of errors.
Consider this.
@table[f][i] = iWhat if, due to some bug, @table[f] returns nil because of a missing key?
Perhaps, f got some unexpected value or something like this? What we will get
with this code is NoMethodError.
@table = {a: [1]}
@table['a'][0] = 2
# => NoMethodError: undefined method `[]=' for nil:NilClassNow, what if we use fetch instead of the first []? It reveals our intent
more clearly, and if something goes wrong fails with a better error:
@table = {a: [1]}
@table.fetch('a')[0] = 2
# => KeyError: key not found: "a"This is for sure a much more descriptive error than the previous one.
I know the code looks ugly. That’s why I proposed changes to the semantics of
[] in the beginning of this post.