views:

479

answers:

2

I came across this syntax while reading a script. I am not sure what is the use of square brackets.

push @data, [ split //, $line ]; #printing this array gives crap values

Or to put into other words what is the difference between the above and the following?

push @data, (split//, $line); #printing this gives actual values

Any suggestions?

+4  A: 

That is from one of my answers:

push @data, [ split //, $line ];

@data is an array of array refs. Each element of @data is a reference to an anonymous array whose entries are the characters in $line.

See also perldoc perlreftut.

Sinan Ünür
+10  A: 

The code:

push @data, (split//, $line);

pushes all items on the current line into @data

and

push @data, [split //, $line];

Pushes a reference to an anonymous array containing those items into @data

If you're only ever processing one value of '$line' its probably more effective to use the former*1 , however, if you are processing a file that contains multiple lines and you want to differentiate between the lines the content is on, the latter is more effective.

Consider:

my @data; 
while( my $line = <$fh> ){
  push @data , ( split //,  $line ); 
}
use Data::Dumper; 
$Data::Dumper::Indent = 0; 
$Data::Dumper::Terse = 1;
print Dumper( \@data );

This will yield all of the bytes read in as separate characters, a single array containing them all, i.e.:

[ "a", "b" , "c" , "\n", "d", "e", "f" ]

When this instead will do something entirely different:

my @data; 
while( my $line = <$fh> ){
  push @data , [ split //,  $line ]; 
}
use Data::Dumper; 
$Data::Dumper::Indent = 0; 
$Data::Dumper::Terse = 1;
print Dumper( \@data );

And will instead group lines like so:

[ [ "a", "b", "c" , "\n" ], [ "d" , "e", "f" , "\n" ] ]

So you can later programmatically traverse it easier.

Note:

 push @data, ( split  //, $line );

and

  push @data, split //, $line;

Are equivalent.

Also,

my @other  = ( 1,2,3 );
push @data, @other ;

and

push @data, 1,2,3;

are equivalent.

From perldoc -f push

push ARRAY,LIST

Treats ARRAY as a stack, and pushes the values of LIST onto the end of ARRAY.  The length of ARRAY increases by the length of LIST.  Has the same effect as

           for $value (LIST) {
               $ARRAY[++$#ARRAY] = $value;
           }

but is more efficient.  Returns the number of elements in the array following the completed "push".

*1: actually, tbf, anyone with half a brain would probably want @data = split //, $line

Kent Fredric
Nicely put: being able to get at specific lines later is key. If you need that, you want the references.
Telemachus
@kent: Thanks! Using examples to explain both conditions helped a lot in understanding the concept.
shubster
@Kent +1 for doing such a good job reading the docs for the OP. Incidentally, anyone with half an interest in Perl ought to know what `[ ... ]` is ... http://stackoverflow.com/questions/1114522/in-perl-how-can-i-read-parts-of-lines-that-match-a-criterion/1114538#1114538 shows the code in question in context.
Sinan Ünür
@Sinan: nobody is born knowing about `[]`, and it's worth remembering that references are never mentioned in _Learning Perl_. I'm not saying that references aren't important for someone serious about Perl, but I suspect that plenty of scripting or maintenance-only Perl coders rarely use references.
Telemachus