Reputation: 1866
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
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
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
Reputation: 139850
You can also use the ||=
operator in this case.
CACHE[key] ||= uncached_method(key)
This is a very common idiom.
Upvotes: 2
Reputation: 12578
In this case, shorter one is preferrable. Ussually =
used in a subexpression is frowned upon, but here it's OK.
Upvotes: 0