ruby has some edge cases which is hard to explain because parsing brings some interesting issues. Here I am listing two of them. If you know of more then add to the list.
def foo
5
end
# this one works
if (tmp = foo)
puts tmp.to_s
end
# However if you attempt to squeeze the above
# three lines into one line then code will fail
# take a look at this one. I am naming tmp2 to
# avoid any side effect
# Error: undefined local variable or method ‘tmp2’ for main:Object
puts tmp2.to_s if (tmp2 = foo)
Here is another one.
def x
4
end
def y
x = 1 if false
x + 2
end
# Error: undefined method `+' for nil:NilClass
puts y
However if you comment out the line x = 1 if false then code will work fine.
In your first example tmp2 is not assigned until it reaches the if statement.
Your second example is not unexpected. Even though x is never assigned it informs the interpreter that you are talking about variable x not function x in the next line. Ruby tries to be pretty loose when determining the context of a name but it will take clues where available. It helps to be specific, for instance: