diff options
-rw-r--r-- | pod/perlfunc.pod | 10 | ||||
-rw-r--r-- | pod/perlsub.pod | 2 | ||||
-rw-r--r-- | t/op/mydef.t | 24 |
3 files changed, 34 insertions, 2 deletions
diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod index a7bbacc9fc..13cfdab3c8 100644 --- a/pod/perlfunc.pod +++ b/pod/perlfunc.pod @@ -2230,6 +2230,11 @@ element of a list returned by grep (for example, in a C<foreach>, C<map> or another C<grep>) actually modifies the element in the original list. This is usually something to be avoided when writing clear code. +If C<$_> is lexical in the scope where the C<grep> appears (because it has +been declared with C<my $_>) then, in addition the be locally aliased to +the list elements, C<$_> keeps being lexical inside the block; i.e. it +can't be seen from the outside, avoiding any potential side-effects. + See also L</map> for a list composed of the results of the BLOCK or EXPR. =item hex EXPR @@ -2615,6 +2620,11 @@ Using a regular C<foreach> loop for this purpose would be clearer in most cases. See also L</grep> for an array composed of those items of the original list for which the BLOCK or EXPR evaluates to true. +If C<$_> is lexical in the scope where the C<map> appears (because it has +been declared with C<my $_>) then, in addition the be locally aliased to +the list elements, C<$_> keeps being lexical inside the block; i.e. it +can't be seen from the outside, avoiding any potential side-effects. + C<{> starts both hash references and blocks, so C<map { ...> could be either the start of map BLOCK LIST or map EXPR, LIST. Because perl doesn't look ahead for the closing C<}> it has to take a guess at which its dealing with diff --git a/pod/perlsub.pod b/pod/perlsub.pod index 969d0ba039..e830130a55 100644 --- a/pod/perlsub.pod +++ b/pod/perlsub.pod @@ -588,6 +588,8 @@ separator. Notably, if you want to work with a brand new value of the default scalar $_, and avoid the potential problem listed above about $_ previously carrying a magic value, you should use C<local *_> instead of C<local $_>. +As of perl 5.9.1, you can also use the lexical form of C<$_> (declaring it +with C<my $_>), which avoids completely this problem. =head3 Localization of elements of composite types diff --git a/t/op/mydef.t b/t/op/mydef.t index 9469ae1fc2..700a3dc5f7 100644 --- a/t/op/mydef.t +++ b/t/op/mydef.t @@ -5,7 +5,7 @@ BEGIN { @INC = '../lib'; } -print "1..48\n"; +print "1..56\n"; my $test = 0; sub ok ($$) { @@ -55,13 +55,15 @@ ok( $_ eq 'global', 's/// on global $_ again' ); $_ = "global"; { + my $_ = 'local'; for my $_ ("foo") { ok( $_ eq "foo", 'for my $_' ); /(.)/; ok( $1 eq "f", '...m// in for my $_' ); ok( our $_ eq 'global', '...our $_ inside for my $_' ); } - ok( $_ eq 'global', '...$_ restored outside for my $_' ); + ok( $_ eq 'local', '...my $_ restored outside for my $_' ); + ok( our $_ eq 'global', '...our $_ restored outside for my $_' ); } { for our $_ ("bar") { @@ -83,10 +85,20 @@ $_ = "global"; ok( /^[67]\z/, 'local lexical $_ is seen in map' ); { ok( our $_ eq 'global', 'our $_ still visible' ); } ok( $_ == 6 || $_ == 7, 'local lexical $_ is still seen in map' ); + { my $_ ; ok( !defined, 'nested my $_ is undefined' ); } } 6, 7; ok( $buf eq 'gxgx', q/...map doesn't modify outer lexical $_/ ); ok( $_ eq 'x', '...my $_ restored outside map' ); ok( our $_ eq 'global', '...our $_ restored outside map' ); + map { my $_; ok( !defined, 'redeclaring $_ in map block undefs it' ); } 1; +} +{ map { my $_; ok( !defined, 'declaring $_ in map block undefs it' ); } 1; } +{ + sub tmap3 () { return $_ }; + my $_ = 'local'; + sub tmap4 () { return $_ }; + my $x = join '-', map $_.tmap3.tmap4, 1 .. 2; + ok( $x eq '1globallocal-2globallocal', 'map without {}' ); } { my $buf = ''; @@ -105,6 +117,14 @@ $_ = "global"; ok( our $_ eq 'global', '...our $_ restored outside grep' ); } { + sub tgrep3 () { return $_ }; + my $_ = 'local'; + sub tgrep4 () { return $_ }; + my $x = join '-', grep $_=$_.tgrep3.tgrep4, 1 .. 2; + ok( $x eq '1globallocal-2globallocal', 'grep without {} with side-effect' ); + ok( $_ eq 'local', '...but without extraneous side-effects' ); +} +{ my $s = "toto"; my $_ = "titi"; $s =~ /to(?{ ok( $_ eq 'toto', 'my $_ in code-match # TODO' ) })to/ |