Spheres of visibility, like rooms in a house
When we talked about variables we mentioned that the most common type of variables is the “local variable”, without explaining any further why they are local. Local to what? Where? We’re finally ready to explain that more.
Since we have now talked about methods, we can also discuss another important concept: scopes.
Wikipedia says: “In programming, the scope of a name is the part of a program where the name is valid: where the name can be used to refer to something else.” (slightly modified to match our own terminology)
Names are known (or defined) in a certain scope, and unknown (or undefined) outside of this scope.
You can think about a scope as of a sphere, a bubble, or a room (with no windows, and doors closed): Certain names, like variable names, are “known” and “visible” inside of the room. Other names, known and visible in another room are not known in this room, but only in the other room.
Every time there is a method call, and the flow of execution enters the method’s body, it enters a new scope, or “room”. Things that are “local” to this method’s scope (i.e. things that are “inside” of the room), are only visible in this scope. Outside of it, they are unknown.
Undefined local variable or method
This is also a good opportunity to talk about an error message that you might see most often. E.g. you’ll see it every time when you made a typo and misspelled a variable or method name.
Consider this code:
def add_two(number) number + 2 end puts add_two(3) puts number
puts add_two(2) will output
5, but the line
puts number will
then raise an error.
This is because the variable
number that is assigned the number
3 when we
call the method is a local variable. It is local to the method’s scope. It
is created when the flow of execution enters the method.
Outside of this scope, when the flow of execution has returned from the method
the method’s scope has been destroyed, and all local variables are gone. The
number is therefore not known, and Ruby raises an error saying
undefined local variable or method 'number'.
If you think about this error message for little bit, does it make sense to you?
We have silently skipped over the fact that, in Ruby, both local variable names and method names, are written the same way: they’re just plain words. For example, here:
number = 2 puts number
number is a local variable, and it is used in the line
def number 2 end puts number
number is the name of a method. And it can be used (called) in the exact same
This is because Ruby, when it executes a program, evaluates one statement after
another. And when it encounters a plain word like
number then it will first
check if, within the current scope, it knows a local variable with the same
name. If so, it will use the value that is associated to this variable. If
there’s no local variable with this name, then it will look for a method. If
there’s also no method with this name it will then raise the error message
undefined local variable or method 'number'.
So the error message is pretty precise, but also sounds kind of convoluted. What it basically tries to say is:
You’ve used the word “number” here, and i don’t know it (in this scope). Did you mean to use a local variable? Or a method?
Does that make sense?
Back to the topic of local scopes. Let’s look at another example:
number = 1 def add_to(number) number + 2 end puts add_to(3)
What do you think the output will be? Will it be
5? Something else?
If you run the code you will see that it’s
The reason for that is that we do assign the number
1 in the outer scope to a
number, but this variable is then never used: the only other line in
the outer scope is the last line
puts add_to(3), and this line does not use
Instead, when the control flow enters the method
add_to Ruby will create a
new local scope, and it will define a new local variable
number which is
assigned the number
3 that was passed to the method. This new variable
number is local to the method’s scope, and therefore this is a different
variable than the one on the very first line, in the outer scope.
We found the following a good metaphor for scopes:
When Ruby enters a method, it’s like she enters a shiny new room in a
house. With her, she brings the objects that are passed as arguments to the
method call. In the example above she brings an object that is the number
Now, as soon as Ruby enters the method, she sticks post-it notes on the
objects, according to the argument list from the method definition. In our
example that is the name
number. So from now on, in this room, there’s a
known local variable that has a value assigned: The object (number)
the post-it note
number on it.
In our example, the outer scope and the scope of the method
two different rooms, and there are two different post-it notes stuck on
two different numbers, which just happen to have the same name on them.