Perl supports anonymous subroutines and closures. Anonymous subroutines are declared with sub without a name and return a reference to the code. A closure is a subroutine that "captures" its lexical scope, including variables that existed when it was created.
Example of an anonymous subroutine and closure:
sub make_incrementer { my $inc = shift; return sub { $_[0] + $inc }; } my $inc10 = make_incrementer(10); print $inc10->(5); # Will print 15
Closures are actively used for creating function factories, generators, and callbacks (for example, in map/grep, event handlers).
An important point: if a closure refers to variables that, in turn, point to the closure itself (directly or through a structure), a circular reference occurs and a memory leak may arise.
When are the variables captured in a closure freed? Is there a difference in behavior for
myandour?
Answer: The my variables captured inside a closure remain alive as long as there is at least one reference to the closure itself. They are not freed when the function finishes; their lifespan is the entire lifespan of the closure. For our variables, such behavior does not apply — they are accessible to all closures and are freed at the end of the program. Forgetting to delete a closure can lead to memory leaks.
Example of the problem:
my $cref; { my $val = 5; $cref = sub { $val++ }; } # $val still exists as long as $cref is alive
Story
In a server application, a closure-context for callbacks was created for each user. However, the closure also referenced the user structure, leading to a circular reference. Because of this, the garbage collector did not clean up user objects even after logout — memory leaks grew exponentially.
Story
In a daemon application for background event processing, closures with captured counter variables were used, but arrays they referenced were forgotten to reset. The result — due to a couple of forgotten closures, old message data accidentally accumulated until the daemon crashed, requiring manual heap cleaning.
Story
A developer attempted to use an
ourvariable in a closure, expecting "closed" behavior — but all closures shared the same variable, leading to data races during parallel execution. The bug manifested when multiple users worked simultaneously with different parameters (erroneous calculations).