0

I cannot figure this out as someone who has primarily worked in C.

How is the following code plausible?

if true hi = "hello" end puts hi 

I'm used to hi not being in the scope of the puts, so it would error. How does scope in Ruby work. I can't seem to find a clear tutorial explaining it.

And even though that's valid, is it good practice?

2 Answers 2

6

In Ruby, there are 5 scopes:

  • script scope
  • module scope
  • class scope
  • method scope
  • block scope

Block scopes nest, the other ones don't. Blocks can close over their lexical environment, the other ones can't. (IOW: not only do they nest inside their lexically surrounding environment, i.e. can access variables from their lexically surrounding environment, they can even continue to do so after that surrounding environment ceases to exist.)

Unlike some other languages, Ruby doesn't have a top-level or global scope for local variables. The "biggest" scope is script scope, but that isn't global, it is confined to a single script. (Usually, a script is the same as a file, but there are Ruby implementations that don't use files, so a term like "file scope" would be misleading.)

Local variables are defined from the point on where their definition is parsed, and initialized from the point on that their definition is executed. In between, when they are defined but not initialized, they evaluate to nil.

Consider this slightly modified example:

if false hi = 'hello' end hi # => nil # hi is defined here, because its definition was parsed if true hi = 'olleh' end hi # => 'olleh' # hi is initialized here, because its definition was executed 
Sign up to request clarification or add additional context in comments.

Comments

1

In Ruby we have 4 scopes -

  1. top level scope
  2. def creates a new scope
  3. class creates a new scope
  4. module creates a new scope.

In your case hi is a local variable which has been created in the top level scope. As I said above if doesn't create a new scope, so it is using the default scope, which is top level scope, and hi is created in the top level scope.

Example :

foo = 12 def baz p foo # undefined local variable or method `foo' bar = 2 end bar # undefined local variable or method `bar' 

As def creates a completely brand new scope, thus inside baz, that scope has no idea about foo and it objects. Similarly, inside the baz, I have created a new variable bar, but it is not known to the out side the scope of baz, thus top level also objects against bar.

3 Comments

blocks create a new scope as well
So is top level scope available all through the def? If I create a variable anywhere, even in a deeply nested if tree with for loops it's available outside of it?
@user212541 No def creates a new scope, which is a brand new and different from top level. For your second question, Yes.