Perl closures and regular variables

I found a possible error in perl closures and $1 regexp variables. They just don't mix.

Take this code.

 use warnings; while ("1234567890"=~/(.)/sg) { push @subs, sub{print $1;}; } for (@subs) {$_->()} 

You can imagine that now perl will now print all numbers - instead, I received 10 warnings from undefined $1 .

Is this really a mistake, or am I just missing something in the perl documentation? Is there any reason why $1 undefined and NOT be part of the closure?

+4
source share
2 answers

I think the answer is similar to the answer for closing perl and $ _ . $1 also a global variable.

What you need to do:

 my $x = $1; push @subs, sub{print $x;}; 
+7
source

Perl has two separate, but largely compatible variable systems. Global variables that are in the symbol table, and lexical variables that are associated with lexical areas in the field.

Global variables can be subject to symbolic dereferencing and are subject to dynamic scope with local . Lexical variables (defined with my ) can be closed.

Regular expression matching variables (and all other Perl special variables) are global variables in the symbol table, so there is no way to close them.

To fix this, simply copy the value to the lexical:

 use warnings; while ("1234567890"=~/(.)/sg) { my $x = $1; # creates a new lexical that the sub closes over push @subs, sub{print $x;}; } for (@subs) {$_->()} 
+8
source

Source: https://habr.com/ru/post/1337244/


All Articles