Item 32: Don t confuse anonymous arrays with list literals.


Item 32: Don't confuse anonymous arrays with list literals.

The anonymous array constructor [ ] looks very much like the parentheses that surround list literals. They both seem to serve the same purposebuilding lists. However, anonymous array constructors differ from list literals in important ways.

An anonymous array constructor returns a reference, not a list

The purpose of an anonymous array constructor is to allow you to create a reference to an array object without having to create a named array:

 { my @arr = 0..9; $aref = \@arr } 

If you didn't have [ ] , you might try this.

Prints 4 .

 print $$aref[4]; 
 $aref = do { \(my @arr = 0..9) };  $aref = [0..9]; 

Or perhaps this.

But you do have [ ] !

You can assign the array references created by anonymous array constructors to array variables, but the result is probably not what you want. Be careful to use array variables with lists, and use scalar variables with anonymous array constructors:

Don't confuse ( ) and [ ] .

 @files = [ glob '*.c' ]; 

Meant to use parentheses, perhaps?

Something like ARRAY(0xa4600) .

 print "@files\n"; 
 @two_d_array = [    [1..3], [4..6], [7..9]  ]; 

The outside should be parentheses, not brackets.

 for $row (@two_d_array) {    print join(',', @$row), "\n";  } 

Yields the enigmatic:

ARRAY(0xa45d0),ARRAY(0xa4654),

ARRAY(0xa4558) .

It's easy to make a similar mistake with hashes and the anonymous hash constructor:

 %vars = {    pi => 3.1416,    ee => 2.7183  } 

Whoopsshould have used parentheses instead of braces, or $vars instead of %vars .

An anonymous array constructor creates a list context, but parentheses don't

List and scalar contexts are created by operators and subroutines. The anonymous array constructor is an operator. Parentheses aren't . Just putting parentheses around something will not change a scalar context into a list context.

You can see this for yourself:

Parentheses do not a list context make.

 sub arrayish {    print "arrayish\n" if wantarray  } 

Will print arrayish if used in a list context.

 $foo = arrayish();  $foo = (arrayish());  $foo = (arrayish(), ()); 

Nope.

Not yet.

Dang, it's stubborn.

 $foo = [ arrayish() ];  ($foo) = arrayish(); 

arrayish

arrayish

This is part but not all of the problem that results if you mistakenly assign a would-be list literal instead of an anonymous array constructor to a scalar variable. The other part of the problem is that when you dereference the scalar variable, Perl will take whatever weird value wound up in the scalar and dereference itperhaps interpreting it as a soft reference. Of course, what you are going to get is total nonsense anyway, but these two effects can combine to make the debugging process difficult by treating you to some very strange behaviors up front. For example:

 $file_list_ref = ( glob '*.c' ); 

Meant to use [ ] instead of parens, probably.

Prints nothing?

Prints foo.c or something.

 print "@$file_list_ref\n";  print "$file_list_ref\n"; 

With all this in mind, a clever reader should be able to figure out what's going on here: [2]

[2] Stumped? The .. operator does not return a list in a scalar context. Instead, it returns a boolean value, which in this case will be falsean empty string, to be exact. So $aref gets the empty string, and $$aref is a soft reference to the "empty string" variable, ${''} .

 $aref = (1..10);  print $$aref;  print $aref; 

Prints nothing?

Also prints nothing?



Effective Perl Programming. Writing Better Programs with Perl
Effective Perl Programming: Writing Better Programs with Perl
ISBN: 0201419750
EAN: 2147483647
Year: 1996
Pages: 116

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net