jackdoe
jackdoe

Reputation: 1866

is it OK to use ruby's implicit return value from []=

I am wandering if it is OK to use ruby's implicit return value when using []= method

[]= uses rb_hash_aset and it is returning val - http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-5B-5D-3D

here is a little code to demonstrate what I mean:

require 'benchmark'
CACHE = {}
def uncached_method(key)
    warn "uncached"
    rand(100)
end
def cached(key)
  CACHE[key] || (CACHE[key] = uncached_method(key))
end
def longer_cached(key)
  return CACHE[key] if CACHE[key]
  CACHE[key] = uncached_method(key)
  CACHE[key]
end

Benchmark.bm(7) do |x|
    y = rand(10000)
    cached(y)
    x.report("shorter:") { 10000000.times do cached(y) end }
    x.report("longer:") { 10000000.times do longer_cached(y) end }
end

of course longer_cached is slower because it does two hash lookups to return cached value, but when you read it line by line it makes more sense then the cached method.

I think using implicit returns is one of the things that makes ruby awesome, but I have always questioned their use when setting values.

So my question is: would you use implicit return from (hash[key] = val)?

Upvotes: 0

Views: 138

Answers (4)

Jörg W Mittag
Jörg W Mittag

Reputation: 369458

Just because nobody mentioned it so far: you are not relying on the return value of Hash#[]=. That return value gets ignored anyway:

class ReturnFortyTwo
  def []=(*)
    return 42
  end
end

r = ReturnFortyTwo.new

r[23] = 'This is the value that is going to be returned, not 42'
# => 'This is the value that is going to be returned, not 42'

In Ruby, assignment expressions always evaluate to the value that is being assigned. No exception. That is guaranteed by the Language Specification. So, I don't see anything wrong with relying on that.

Upvotes: 2

Stefan
Stefan

Reputation: 114178

I'd keep it as simple and clean as possible (it's faster, too):

def cached(key)
  value = CACHE[key]
  unless value
    value = uncached_method(key)
    CACHE[key] = value
  end
  value
end

Upvotes: 0

hammar
hammar

Reputation: 139850

You can also use the ||= operator in this case.

CACHE[key] ||= uncached_method(key)

This is a very common idiom.

Upvotes: 2

Boris Stitnicky
Boris Stitnicky

Reputation: 12578

In this case, shorter one is preferrable. Ussually = used in a subexpression is frowned upon, but here it's OK.

Upvotes: 0

Related Questions