dr jerry
dr jerry

Reputation: 10026

How to reference a split expression in Perl?

I want to create a reference to an array obtained by a split in Perl. I'm thinking something like:

my $test = \split( /,/, 'a,b,c,d,e');

foreach $k (@$test) {
   print "k is $k\n";
}

But that complains with Not an ARRAY reference at c:\temp\test.pl line 3. I tried a few other alternatives, all without success.

Upvotes: 17

Views: 5831

Answers (3)

Gimley Farb
Gimley Farb

Reputation: 1

Giving it a name has different semantics in that changes to the named variable then change what was referenced while each anonymous array is unique. I discovered this the hard way by doing this in a loop.

Upvotes: 0

Sinan Ünür
Sinan Ünür

Reputation: 118118

Background explanation:

split, like other functions, returns a list. You cannot take a reference to a list. However, if you apply the reference operator to a list, it gets applied to all its members. For example:

use Data::Dumper;

my @x = \('a' .. 'c');

print Dumper \@x

Output:

$VAR1 = [
          \'a',
          \'b',
          \'c'
        ];

Therefore, when you write my $test = \split( /,/, 'a,b,c,d,e');, you get a reference to the last element of the returned list (see, for example, What’s the difference between a list and an array?). Your situation is similar to:

Although it looks like you have a list on the righthand side, Perl actually sees a bunch of scalars separated by a comma:

my $scalar = ( 'dog', 'cat', 'bird' );  # $scalar gets bird

Since you’re assigning to a scalar, the righthand side is in scalar context. The comma operator (yes, it’s an operator!) in scalar context evaluates its lefthand side, throws away the result, and evaluates it’s righthand side and returns the result. In effect, that list-lookalike assigns to $scalar it’s rightmost value. Many people mess this up becuase they choose a list-lookalike whose last element is also the count they expect:

my $scalar = ( 1, 2, 3 );  # $scalar gets 3, accidentally

In your case, what you get on the RHS is a list of references to the elements of the list returned by split, and the last element of that list ends up in $test. You first need to construct an array from those return values and take a reference to that. You can make that a single statement by forming an anonymous array and storing the reference to that in $test:

my $test = [ split( /,/, 'a,b,c,d,e') ];

Upvotes: 35

Birei
Birei

Reputation: 36262

Surround split command between square brackets to make an anonymous reference.

my $test = [ split( /,/, 'a,b,c,d,e') ];

Upvotes: 20

Related Questions