Ruby Tuesday – Array#fetch

Today’s Ruby Tuesday covers a variation of one of my personal favorite set of Ruby methods, Array#fetch.

Array.fetch takes an integer for an argument and gets the element for a given index, using 0-based index scheme.

icao = [:alpha, :bravo, :charlie, :delta, :foxtrot]
# => [:alpha, :bravo, :charlie, :delta, :foxtrot]
icao.fetch 1
# => :bravo
icao.fetch 0
# => :alpha

It also can get you the elements walking backward from a list

icao.fetch -1
# => :foxtrot
icao.fetch -4
# => :bravo

If an index is out of bounds of the array, either positive of negative, an IndexError is raised.

icao.fetch 5
# IndexError: index 5 outside of array bounds: -5...5
# from (pry):5:in `fetch'
icao.fetch -7
# IndexError: index -7 outside of array bounds: -5...5
# from (pry):11:in `fetch'

At this point, I can hear you saying:

So what?! I can do this using a subscript to an array and not get exceptions but a nil when something is not found.
–You

icao[4]
# => :foxtrot
icao[0]
# => :alpha
icao[-1]
# => :foxtrot
icao[-7]
# => nil
icao[5]
# => nil

And you would be right.

But where you might run into trouble with just using a subscript index, is if you have nils in your array.

some_nils[2]
# => nil
some_nils[100]
# => nil

This is where Array#fetch makes its way to one of my favorite Ruby methods.

When you decide to use Array#fetch over just subscripts, you can specify a default value that you get back if the index is out of bounds.

icao.fetch 2, :fubar
# => :charlie
icao.fetch 5, :snafu
# => :snafu
icao.fetch -7, :fubar
# => :fubar

And to top it off, you can even pass a whole block which is called with the index passed to fetch, so you can do more detailed logic if needed.

icao.fetch(-7) { |index| "SNAFU occured trying to fetch with index #{index}" }
# => "SNAFU occured trying to fetch with index -7"

–Proctor