In Perl, there are three main types of variable declarations: my, our, and state.
sub example_state { state $counter = 0; $counter++; return $counter; } for (1..3) { print example_state(), " "; # Will output 1, then 2, then 3 }
Where to use them properly:
my — almost always the preferred choice for variables unless there is a reason for global access.our — for exporting variables between modules when shared access is required.state — when a variable should "remember" its value between function calls (e.g., a call counter).Can a variable declared with our be captured in a closure just like my?
Typically, the answer is "yes, it's convenient," but that's not the case. An our variable is global to the package, and closure essentially does not bind its value at the time of closure creation but accesses it through a global name. Therefore, its "value" can change from outside the closure and affect all closures!
our $x = 10; my $closure = sub { return $x; }; $x = 42; print $closure->(); # Will return 42, not 10
Story
In a large script for parsing logs, variables were declared using our for "convenient access" from different functions of the module. As a result, changing these variables in one function led to unexpected behavior in another, breaking the parallel log processing.
Story
Using my for variables whose value needed to be retained between function calls (like a counter within a recursive traversal) resulted in the value being reset on each call, leading to incorrect traversal logic. Switching to state fixed the issue.
Story
Incorrect use of our in an imported module (exporting variables not through Exporter) caused a name collision when importing two different modules that used the same variable name. Consequently, data "jumped" from one context to another.