Scope of Variables Redux

In this chapter, you will learn about the visibility of local variables in the context of dynamic language constructs such as define_method, Class.new and Module.new.

Scope

How does dynamically defining methods, classes and modules affect the local variable visibility?

At the Top Level

Visibility of Local Variable

x = 1

p "At top level x : #{x}"

define_method(:test) do
  p "Inside top level method x : #{x}"
end

test

This prints:

At top level x : 1
Inside top level method x : 1

The local variable is visible inside the dynamically defined method.

The x at Top Level and Inside Method

We can verify it by checking the local variables.

x = 1

p "At top level local_variables is : #{local_variables}"

define_method(:test) do
  p "Local variable inside the method : #{local_variables}"
end

test
p "Back at the top level local_variables is : #{local_variables}"

This prints:

At top level local_variables is : [:x]
Local variable inside the method : [:x]
Back at the top level local_variables is : [:x]

The local variable defined at the top level is visible inside the dynamically defined method.

The Value of Self

Does the value of self change? Let's check:

x = 1

p "At top level self : #{self}"

define_method(:test) do
  p "Inside top level method self : #{self}"
end

test

This prints:

At top level self : main
Inside top level method self : main

The value of self remains the same.

Self at Top Level and Inside Dynamically Defined Method

Inside the Top Level Method

x = 1

p "At top level x is : #{x}"

define_method(:test) do
  x = 2
  p "Inside the top level method x is : #{x}"
end

test
p "Back at the top level x is : #{x}"

This prints:

At top level x is : 1
Inside the top level method x is : 2
Back at the top level x is : 2

The scope did not change. Thus, the x at the top level and inside the method is the same.

The Scope at the Top Level and Inside Method

At the Top Level

Inside a Class

Let's check if we can see the local variable declared at the top level from inside a dynamically defined class.

x = 1

p "At top level x : #{x}"

Car = Class.new do
  p "Inside the Car class x : #{x}"
end

This prints:

At top level x : 1
Inside the Car class x : 1

The local variables defined at the top level is visible inside the Car class.

The Value of Local Variable at Top Level and Inside Method

We can print the local variables to verify that the variable x is the same.

x = 1

p "At top level : #{local_variables}"

Car = Class.new do
  p "Inside the Car class : #{local_variables}"
end

This prints:

At top level : [:x]
Inside the Car class : [:x]

Value of Self

Does the value of self change? Let's check:

x = 1

p "At top level, self : #{self}"

Car = Class.new do
  p "Inside the Car class, self : #{self}"
end

This prints:

At top level, self : main
Inside the Car class, self : #<Class:0x007fff331c45f0>

The self changes from main to an instance of Class.

The Self at Top Level and Inside Class

Variable with Same Name Inside a Class

What happens when you have a variable with the same name inside the class?

x = 1

p "At top level x : #{x}"

Car = Class.new do
  x = 2
  p "Inside the Car class x : #{x}"
end

p "Back at the top level : #{x}"

This prints:

At top level x : 1
Inside the Car class x : 2
Back at the top level : 2

This changes the value of the same local variable defined at the top level.

At the Top Level

Inside a Module

Let's check if we can see the local variable declared at the top level from inside a dynamically defined module.

x = 1
p "At top level x : #{x}"

Driveable = Module.new do
  p "Inside the Driveable module x : #{x}"
end

This prints:

At top level x : 1
Inside the Driveable module x : 1

The local variables defined at the top level is visible inside the do-end block of creating a module.

The Local Variable at the Top Level and Inside Module

We can print the local variables to verify it.

x = 1

p "At top level : #{local_variables}"

Driveable = Module.new do
  p "Inside the Driveable module : #{local_variables}"
end

This prints:

At top level : [:x]
Inside the Driveable module : [:x]

Value of Self

Does the value of self change inside the do-end block? Let's check:

x = 1

p "At top level, self : #{self}"

Driveable = Module.new do
  p "Inside the Driveable module, self : #{self}"
end

This prints:

At top level, self : main
Inside the Driveable module, self : #<Module:0x007f840>

The self changes from main to an instance of Module.

The self at Top Level and Inside Module

Variable with Same Name Inside a Module

What happens when you have a variable with the same name inside the do-end block of creating a Module?

x = 1

p "At the top level, x : #{x}"

Driveable = Module.new do
  x = 2
  p "Inside the Driveable module, x : #{x}"
end

p "Back at the top level, x : #{x}"

This prints:

At the top level, x : 1
Inside the Driveable module, x : 2
Back at the top level, x : 2

This changes value of the same local variable defined at the top level.

Samle Local Variable at Top Level and Method Level Scope

Key Takeaways

  • The local variable defined at the top level is visible inside the dynamically defined method.
  • The scope does not change. Thus, the x at the top level and inside the method is the same.
  • The local variables defined at the top level is visible inside the do-end block of creating the Car class.
  • The scope does not change. Thus, the x at the top level and inside the do-end block of creating a new instance of Class is the same.
  • The self changes from main to an instance of the Class.
  • The local variables defined at the top level is visible inside the do-end block of creating the Driveable module.
  • The scope does not change. Thus, the x at the top level and inside the module is the same.
  • The self changes from main to an instance of Module.

Here is a summary of what happens to self and scope when we use dynamic language constructs of Ruby.

Self Scope Where
No Change No Change Top Level and Top Level Method
Changes No Change Top Level and Inside Class
Changes No Change Top Level and Inside Module

Summary

In this chapter, you learned that when we dynamically define a method, class or module, the scope does not change. The dynamic creation of a method does not change the value of self, it remains main. For dynamic creation of class and module, the self changes as summarized in the table.

Dynamic Construct Self
Class.new Instance of Class
Module.new Instance of Module

results matching ""

    No results matching ""