RockPaperScissors

LizardSpock

Setting Ruby Defaults '||' vs 'Fetch(){}'

| Comments

There is a very good presentation Confident Code by Avdi Grimm author of http://exceptionalruby.com/. Previously presented at Cascadia.

There are many points which I find interesting, the most interesting for me are the ones which I disagree with, probably due to not understanding them in full.

I use to do this for setting defaults.

def something( a, options={} )
  width = options[:width]
  width ||= 40
end

I had not realized that this could be shortened to:

def something( a, options={} )
  width = options[:width] || 40
end

Avdi recommends that you use fetch instead (see below) as this has one less comparison. It is actually a longer statement and at the end replaces || 40 with {40} both just as ambiguous to non ruby programmers. So I have a preference for neither based on readability.

def something( a, options={} )
  width = options.fetch(:width) { 40 }
end

Maybe the ‘one less comparison’ argument has some holding on execution time. NB: Tested with ruby 1.9.2-p290

The Test:

require 'benchmark'

def pipe options
  width = options[:width]
  width ||= 40
  return width
end

def pipe_clean options
  width = options[:width] || 40
  return width
end

def fetch options
  width = options.fetch(:width) { 40 }
  return width
end

n = 100_000_000
Benchmark.bmbm do |x|
  options={}
  x.report("options \\n ||= 40    :") { n.times { pipe(       options ) } }
  x.report("options[] ||      40 :")  { n.times { pipe_clean( options ) } }
  x.report("options.fetch() {40} :")  { n.times { fetch(      options ) } }
end

The Results:

Rehearsal ----------------------------------------------------------------------
options \n ||= 40    :  30.700000   0.000000  30.700000 ( 30.702585)
options[] ||      40 :  28.480000   0.010000  28.490000 ( 28.492345)
options.fetch() {40} :  38.720000   0.000000  38.720000 ( 38.731869)
------------------------------------------------------------ total: 97.910000sec

                                         user     system      total        real
options \n ||= 40    :  30.490000   0.000000  30.490000 ( 30.494530)
options[] ||      40 :  28.400000   0.000000  28.400000 ( 28.399310)
options.fetch() {40} :  39.230000   0.000000  39.230000 ( 39.234303)

Since I am ambivalent to the 2 styles ‘||’ vs ‘fetch(){}’ I think I will go with the 27% faster ‘||’ version.

Comments