ohspite
ohspite

Reputation: 1319

Why is assignment treated differently in this single line conditional?

I've read a few things, including this and this, but I think the below example is different than what they're talking about. One person actually raises a similar example in the discussion but it's ignored.

So, run in irb (ignore the warnings about assignment in the conditional):

(puts x) if (x = 0) # NameError: undefined local variable or method `x'...
x                   # => 0
(puts x) if (x = 0) # "0", => nil

but the second time there's no error.

Does this make any sense, even in a "once you understand what the parser is really doing and that this just some optimization it all becomes clear" kind of way? Because to me, it seems pretty undesirable.

To be clear, the above conditional should be equivalent (right?) to

if newvar=0
  puts newvar
end

which does not raise an error.


Update: There have been even more posts on this topic since this question was asked. For example,
http://seejohncode.com/2012/07/31/ruby-gotcha-single-line-conditionals/.

Upvotes: 2

Views: 138

Answers (4)

DGM
DGM

Reputation: 26979

I think the difference in this case is whether the variable exists when it parses the line. In the case of:

if x=0
  puts x
end

the variable x is defined before it parses the line that uses x.

In other words, the error message is a parse time error, not a runtime error.

Upvotes: 1

Serabe
Serabe

Reputation: 3924

First, check that you mean x=0 in the conditional clause.

Second, puts x if x = 0 is not equivalent to:

if x = 0
  puts x
end

In your case, x is not declared yet for puts x so it cannot see it.

Upvotes: 0

Jacob
Jacob

Reputation: 23225

Oddly enough, this works fine in Rubinius:

Welcome to IRB. You are using rubinius 1.2.4dev (1.8.7 7ae451a1 yyyy-mm-dd JI)
>> (puts x) if (x = 0) #=> nil
0

I'm inclined to say it's a weird parsing bug in MRI.

Upvotes: 1

Dnyan Waychal
Dnyan Waychal

Reputation: 1418

I think in this you are assigning 0 to x.

(puts x) if (x = 0)

i think it should be

(puts x) if (x == 0)

Upvotes: 0

Related Questions