More docs and tests for "my $_".
Rafael Garcia-Suarez [Tue, 3 Feb 2004 21:54:23 +0000 (21:54 +0000)]
p4raw-id: //depot/perl@22265

pod/perlfunc.pod
pod/perlsub.pod
t/op/mydef.t

index a7bbacc..13cfdab 100644 (file)
@@ -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
index 969d0ba..e830130 100644 (file)
@@ -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
 
index 9469ae1..700a3dc 100644 (file)
@@ -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/