开发者

I don't understand ruby local scope

In this example,

def foo(x)
  if(x > 5)
    bar = 100
  end
  puts bar
end

Then foo(6) Outputs: 100 and 开发者_Go百科foo(3) outputs nothing.

However if i changed the definition to

def foo(x)
  if(x > 5)
    bar = 100
  end
  puts bob
end

I get an "undefined local variable or method" error.

So my question is why I am not getting this error when I call foo(3) and bar is never set?


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.


I'm not sure what you're asking. Running foo(3) with the second definition will always give an error, since bob is never defined. The argument to the method doesn't change that.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜