What is the difference between these two lines of code?
a = (b if (b = "test"))
a = b if (b = "test")
The first runs fine and sets both a
and b
to test
, but the second throws an error:
NameError: undefined local variable or method `b' for main:Object
I would have assumed that for the second line, Ruby would evaluate b = "test"
first, then if "test"
, and finally a = b
. What is actually going on?
(Ruby version 2.2.4)
Both lines won't work. And both lines will work. It is schrödinger expression :).
You can run it twice in a new repl:
a = b if b = "test"
#=> NameError: undefined local variable or method `b' for main:Object
a = b if b = "test"
#=> "test"
Let's look deeper, open a new repl:
defined(b)
#=> nil
a = b if b = "test"
#=> NameError: undefined local variable or method `b' for main:Object
defined(b)
#=> local-variable
b
#=> "test"
a = b if b = "test"
#=> "test"
So actually Ruby has evaluated b = "test"
part and defined this variable in current scope. Both expressions a = b
and if b = "test"
were executed. More than it, if statement is executed before assignment statement:
c = p("assignment") && b if b = p("if") && "test"
#=> "if"
#=> "assignment"
#=> NameError: undefined local variable or method `b' for main:Object
But b
variable was not defined in scope of assignment statement when it was evaluated first time. And on the second approach it was already defined so you received correct result.
So, Never do assignments in this way