Reputation: 9
I have a curiosity with variable definition. I know about variable definition, it's just to understand how it works. The idea is to set myvar to 0 if it is not defined. I don't want to use false because false could be returned by false or nil.
def foo
myvar=1000
myvar = ((defined? myvar)==nil) ? 0 : myvar
puts myvar
end
foo # => 1000
but
def foo
# myvar=1000
myvar = ((defined? myvar)==nil) ? 0 : myvar
puts myvar
end
foo # => nil
but
def foo
mybool = ((defined? myvar)==nil)
myvar = mybool ? 0 : myvar
puts myvar
end
foo # => 0 it rocks !
It's like if the boolean test was affected to myvar before the final test was evaluated.
((defined? myvar)==nil)
gives 2 possibilities defined? myvar could be nil
or the right side of test nil
could be nil
(it's nil
).
To get rid of the nil part of this test, I tried this code :
def foo
mylocalvariable = 2 # it gives 'local-variable' and not nil
puts ((defined? myvar) == (defined? mylocalvariable ))
myvar = ((defined? myvar)!=(defined? mylocalvariable )) ? 0 : myvar
puts myvar
end
foo # => nil
It seems the first part of the test was affected to myvar, but assignment operators come after () or after comparison operator. Do you have an idea? I don't want an other code but just why it works like that. Thank you.
Upvotes: 0
Views: 242
Reputation: 9
I know why. When you code myvar= and you test defined?myvar, ruby consider myvar defined. If you remove myvar= , myvar is considered undefined in the test. The left part is read before the right part.
Upvotes: 0
Reputation: 2754
Hi this kind of operator is ternary operator.
Example:
@x = 1
@y = 2
@x>2 ? puts "YES" : puts "NO"
You can also check if it for an ActiveRecord
Example:
@x = User.find(:all, :conditions => ["id = ?", 1])
@x.nil? ? puts "Null" : puts "Not Null"
Upvotes: 0
Reputation: 160551
You might not want other code, but you need some because you're going the long way around to accomplish something that is simple. If you want to set an undefined variable to 0 use:
myvar ||= 0
How does it work? ||=
is a conditional assignment operator, that basically looks at the variable being assigned to on the left, and, if it's nil or false, assigns the value on the right to it. It's a trick found in many languages.
Ternary (?:
) statements are useful for small if/then/else
statements, but aren't really the right choice for what you want to do. Instead, if you want to use something besides ||=
, use:
myvar = 0 unless myvar
Again, all of these will reassign myvar
if it happens to be a false
value, not just if it's nil. That's a potential problem, but, as developers, we're supposed to be in control and should have a good idea what type of value a variable is holding at any moment so it shouldn't be that big of a problem.
Upvotes: 3