ProgrammingPerl Developer / Lead Developer for Supporting Perl Projects

Explain how lexical and dynamic scoping works in Perl when using my, local, and our, and provide examples of problems arising from a misunderstanding of these differences.

Pass interviews with Hintsage AI assistant

Answer

In Perl, variables can have lexical or dynamic scope.

  • my creates a variable with lexical scoping: the variable is visible only within the block where it is defined.
  • local temporarily overrides the value of a global (package) variable with dynamic scoping: the new value is visible in all called functions until exiting the block.
  • our defines a global (package) variable, but it is only visible in the current lexical block.

Example:

our $x = 10; sub test_my { my $x = 20; inner(); } sub test_loc { local $x = 30; inner(); } sub inner { print $x; } test_my(); # Prints 10 — my $x is not visible from inner $| = 1; test_loc(); # Prints 30 — local $x is visible from inner

local is used to change package variables of special types like $_, $/, $@, etc.

Trick Question

What will be the result of executing the following code and why?

our $a = 5; sub outer { my $a = 10; inner(); } sub inner { print $a; } outer();

Answer: Prints 5. Because the my variable $a from outer is not visible from inner; the package variable $a declared with our is used.

Examples of real errors due to ignorance of the topic's nuances


Story

In a log analysis script, statistics were logged into a global hash using local, thinking that they were changing the value only within the block. It turned out that the change through local spread to other parts of the program, leading to data loss.

Story

In module testing, many developers were overriding global special variables like $/ (line separator) with my, resulting in no changes occurring, and tests “failing” in strange ways only partially.

Story

In JavaScript development, after switching to Perl, developers habitually tried to declare variables using our everywhere unnecessarily, leading to unexpectedly global variables that hindered encapsulation and caused name collisions.