orrganik
orrganik

Reputation: 9

?: operator in ruby and variable definition

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

Answers (3)

orrganik
orrganik

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

AllenC
AllenC

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

the Tin Man
the Tin Man

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

Related Questions