I don't understand ruby local scope
There a couple of things going on here. First, variables declared inside the if
block have the same local scope as variables declared at the top level of the method, which is why bar
is available outside the if
. Second, you're getting that error because bob
is being referenced straight out of the blue. The Ruby interpreter has never seen it and never seen it initialized before. It has, however, seen bar
initialized before, inside the if statement. So when is gets to bar it knows it exists. Combine those two and that's your answer.
Your second example is actually a red herring: the reason why you are getting an exception is not because bob
is uninitialized, it's because it is ambiguous. It's impossible to tell whether it's a variable or a method.
Your first example works, because uninitialized local variables (as well as global variables and instance variables) evaluate to nil
. Therefore, puts bar
is perfectly fine: in one case bar
is initialized to 100
and this evaluates to 100
, in the other case it is uninitialized and thus evaluates to nil
. puts
calls to_s
on its argument, which is defined for nil
(it simply returns the empty string), so everything is fine and dandy.
See also In Ruby, why after starting irb, foo.nil? says undefined error, and @foo.nil? gives “true”, and @@wah.nil? gives error again?
So don't take this as gospel (since it is more based on observation then understanding), but it seems like the ruby interpreter will flag any word (without a sigil in front of it) to the left of an equals sign as a local. Your example is strange, this is even more bizarre
def foo
bar = bar
puts bar // nil, which gets coerced into ""
end
I don't understand why or how it works, but there you have it.
foo(3)
doesn't output nothing. It outputs a newline.
Using inspect
would give you more of a hint:
def foo(x)
if(x > 5)
bar = 100
end
puts bar.inspect
end
foo(3)
prints out
nil
bar
is a fully-fledged variable, which just happens to have a value of nil
.