5

I wonder, why is a visible?

if true
  puts 'true'
else
  puts 'false'
  a = 123
end

puts a # no error

# or 
# my_hash = {key: a}
# puts my_hash # :key => nil

But this causes an error, even though there will be 'true' shown

if true
  puts 'true'
else
  puts 'false'
  a = 123
end

puts a2 # boooooom
Alan Coromano
  • 24,958
  • 53
  • 135
  • 205
  • 2
    See accepted answer on [this question](http://stackoverflow.com/questions/12928050/why-does-ruby-seem-to-hoist-variable-declarations-from-inside-a-case-statement-e?rq=1#) – Charles Caldwell Apr 02 '13 at 17:15

1 Answers1

1

Referencing a inside the if has the effect of declaring it as a variable if there is no method a= defined for the object.

Since Ruby does not require methods to be called using the same syntax as referencing a variable or assigning to one, it needs to make an assessment as to the nature of the token in question. If it could be a method call because a method with that name has been defined, then it will be interpreted as such. If no such method exists at the time the source is compiled, then it will be a variable by default.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • 1
    "value should be scoped to the `if` block"? I'm not sure what that means? Variables are scoped, and `a` is not scoped to the `if`. – Neil Slater Apr 02 '13 at 17:23
  • 4
    `if` has no block, only clauses that are conditionally evaluated. The clauses of an `if` statement do not create a new scope. This is not C. – sfstewman Apr 02 '13 at 17:41
  • I've always treated the `if` as if it was scoped, but you're right, that doesn't appear to be the case. C++ habits refuse to go away. Variables will be scoped to the method they're declared inside of, or the `main` context if in `irb`. – tadman Apr 02 '13 at 17:56
  • Whether or not there is a method `a=` defined is completely irrelevant. `a = foo` will *always* assign to a local variable called `a`. In fact, that is how Ruby distinguishes between variables and methods in the first place! If you want to call a setter called `a=`, you *have* to use `self.a = foo`. That's why setters are exempt from the privacy rule that `private` methods can only be called without an explicit receiver, because there wouldn't be a way to call a private setter otherwise. – Jörg W Mittag Apr 02 '13 at 23:02