On Mon, Oct 11, 2010 at 3:05 PM, Charles C. [email protected] wrote:
I usually do:
hash = { :key1 => nil , :key2 => “aBcD” }
var = hash[:key1] && hash[:key1].downcase
var # => nil
var = hash[:key2] && hash[:key2].downcase
var # => “abcd”
Notice the nuance that if hash[:key1] is false, that will be assigned to
var.
This also works:
var = hash[:key1].downcase rescue nil
var # => nil
var = hash[:key2].downcase rescue nil
var # => “abcd”
But people seem to really be opposed to doing this. Not entirely sure why.
Maybe because it wouldn’t raise an error if, for example, you put some
absurd type of data in your hash?
But people seem to really be opposed to doing this. Not entirely sure why.
Maybe because it wouldn’t raise an error if, for example, you put some
absurd type of data in your hash?
Absurd? It’s an easy to get symbols where strings should be…
key = “a”
hash = {“a” => :Foo}
var = hash[key].downcase rescue nil
p var # ==> nil
Is there a more idiomatic way to do the following?
var = hash[key].nil? ? nil : hash[key].downcase
Note that if hash[key] is nil, I want nil assigned to var, so this
won’t work:
var = hash[key].downcase unless hash[key].nil?
It actually will work if var has not been initialized before. But that’s
more or less an artifact of how the parser treats local variable
assignment expressions, and is pretty fragile:
No! Blanket rescue statements are not to be used. It’s a trivial
example, sure, but still.
if hash.has_key?(:key) and hash[:key].is_a?(String)
do stuff
end
Or, your rescue example… I’d at least rewrite it as:
var = begin
hash[key].downcase
rescue NoMethodError
nil
end
If you use Ruby Ketsup (aka, Active Support), you can put this
everywhere:
val = hash[key] if hash[key].present? #or…
val = hash[key] unless hash[key].blank?
So you know why you’re rescuing here. Blanket rescue foolishness can
and will cascade throughout your application. Again, trivial
example… But I think it shouldn’t really be done in any
circumstance.
Because I love dead horses (or just low productivity). Two more code
examples:
Just get a String, rawr
var = begin
hash[key].to_s.downcase
rescue NoMethodError
“”
end
Be a good citizen, and tread carefully
var = case hash[key]
when String then hash[key].downcase
when Numeric then hash[key].to_s
when Array then hash[key].join.downcase # rescue block for
safety?
when Hash then hash[key].values.join.downcase # rescue
block for safety?
else puts “LOOK AT WHAT YOU’VE DONE. YOU’VE MADE
RUBY CRY.”
end
Haskell solves the “may be nil” problem with the Maybe monad (from
Haskell).
There’s many ways to implement something similar… such as implementing
Object#maybe whose method_missing (e.g. Maybe#method_missing) proxies to
the
original object. NilClass can also implement #maybe, and always return
nil.
It actually will work if var has not been initialized before. But that’s
more or less an artifact of how the parser treats local variable
assignment expressions, and is pretty fragile:
Exactly. Plus, it’s programming by side effect, which gives me the
willies. I wondered if someone would bring it up, though.
Note that if hash[key] is nil, I want nil assigned to var, so this
hash = { :key1 => nil , :key2 => “aBcD” }
var = hash[:key1] && hash[:key1].downcase
var # => nil
var = hash[:key2] && hash[:key2].downcase
var # => “abcd”
Using the short-circuit evaluation of && to avoid calling downcase.
Interesting.
Notice the nuance that if hash[:key1] is false, that will be assigned to
var.
Yes, that’s a weakness of the technique, though it wouldn’t matter in
the use case at hand.
absurd type of data in your hash?
I don’t have enough experience with exception handling in Ruby to know
for sure, but I suspect that it’s considered a bad practice because it
might accidentally catch exceptions other than the intended one. It’s
being discussed in another subthread, so I’ll watch that.
which I indicated in my original post won’t work, as I want an
explicit assignment of nil to var in the event that hash[key] returns
nil. See David Black’s response to my post. I’m not assuming that
this is the first occurrence of var, so it may already have a value
from a previous assignment.
which I indicated in my original post won’t work, as I want an
explicit assignment of nil to var in the event that hash[key] returns
nil. See David Black’s response to my post. I’m not assuming that
this is the first occurrence of var, so it may already have a value
from a previous assignment.
You can get around this by putting ( ) around the whole if clause:
var = (hash[key].downcase if hash[key])
It works because (… if …) returns nil if the condition is false.
On Tue, Oct 12, 2010 at 6:39 AM, Rick DeNatale [email protected]wrote:
Nobody seems to have mentioned it, I guess since this is the place for
‘pure’ rubyists, but Rails has the following methods:
So with this you can write simply
var = hash[key].try(:downcase)
That’s pretty cool, but I’d prefer it return a proxy object for all
non-nil
objects that just relays the method call, and for nil a proxy that
always
returns nil, ala: