Why does it work? (variable scope)

Two similar cases (same behavior):


my_var = 123 if false

puts my_var
=> nil


if false
my_var = 123
end

puts my_var
=> nil

Somebody could expect that “puts my_var” should raise “NameError:
undefined local variable or method `my_var’” in both cases.

So I can understand that in case 1) the Ruby interpreter knows about
my_var variable since it reads it before checking the “if”. But in
case 2) It seems that my_var variable is known when the script/file is
loaded since the interpreter will never run into the “if false”
statement.

Am I right? Thanks a lot.

BTW:


puts “1: defined? my_var: #{(defined? my_var).inspect}”

if false
my_var = 123
end

puts “2: defined? my_var: #{(defined? my_var).inspect}”

=>
1: defined? my_var: nil
2: defined? my_var: “local-variable”

On Mon, Sep 10, 2012 at 4:57 PM, Iaki Baz C. [email protected]
wrote:

undefined local variable or method `my_var’" in both cases.
The issue with expectations is that sometimes they aren’t met. :slight_smile:

So I can understand that in case 1) the Ruby interpreter knows about
my_var variable since it reads it before checking the “if”. But in
case 2) It seems that my_var variable is known when the script/file is
loaded since the interpreter will never run into the “if false”
statement.

Am I right? Thanks a lot.

Mostly. The variable is known from the lexical position in the code
where it is defined - even if that code is not executed - as you found
out:

=>
1: defined? my_var: nil
2: defined? my_var: “local-variable”

That’s also the reason why these behave differently although they seem
to do the same:

$ ruby -e ‘if x.nil?; x=123; end; p x’
-e:1:in <main>': undefined local variable or method x’ for
main:Object (NameError)
$ ruby -e ‘x=123 if x.nil?; p x’
123

Kind regards

robert

Hi,

Local variables are determined purely by the existence of an assignment
expression in the current scope. It doesn’t matter if the assignment is
ever executed.

Also note that there’s no difference between “if … end” and “… if
…” with regard to the order of evaluation. In both cases the condition
is evaluated first, and if it evaluates to true, the body is executed.

Clear. Thanks a lot to all.

2012/9/10 Robert K. [email protected]:

Jan E. писал 10.09.2012 19:14:

…" with regard to the order of evaluation. In both cases the
condition
is evaluated first, and if it evaluates to true, the body is
executed.

Exactly.

If existence of a local variable would be determined by the matter of
it
being executed, that would create an awful ambiguity. For example:

def a(q)
if q
b = 1
end
b
end

would sometimes return 1, and sometimes call a method b.

Things would get much worse if loops and scopes are involved.