3

I haven't programmed in Perl in over 10 years so maybe this is something obvious to more experienced Perl programmers. I searched for an answer but didn't find anything.

My question is: why are references to anonymous arrays scalar?

For example in the following code:

#!/usr/bin/perl

use strict;
use feature qw(say);

my @array1 = ('one');
say 'array ref 1: ' . \@array1;
my @array2 = ('one', 'two');
say 'array ref 2: ' . \@array2;
say 'array ref 3: ' . \('one');
say 'array ref 4: ' . \('one', 'two');

exit 0;

The result is:

array ref 1: ARRAY(0x1e1b1c0)
array ref 2: ARRAY(0x1e1b190)
array ref 3: SCALAR(0x1e1b280)
array ref 4: SCALAR(0x1e10c40)

Why are array ref 3 and array ref 4 scalar?

0xfeedbacc
  • 301
  • 2
  • 9
  • Try also `say 'array ref 5: ' . ['one', 'two'];` – aschepler Dec 10 '15 at 14:56
  • 6
    There are no anonymous arrays in your examples :-) – Dave Cross Dec 10 '15 at 15:42
  • 2
    This is explained in [Arrays vs. Lists in Perl: What's the Difference?](http://friedo.com/blog/2013/07/arrays-vs-lists-in-perl) under "Arrays can be referenced." (I recommend reading the rest of the article, too, since many Perl programmers don't realize that there's a difference between lists and arrays.) – ThisSuitIsBlackNot Dec 10 '15 at 15:53
  • 1
    Thanks ThisSuitIsBlackNot I read that article about Arrays vs Lists and it cleared things up. – 0xfeedbacc Dec 10 '15 at 16:44

3 Answers3

14

All references are scalars. When you stringify a reference, it includes the type of what it's referencing. That means you have a reference to a scalar.

[ ] is the operator that constructs an array. ( ) doesn't create any arrays.

You want

say 'array ref 3: ' . ['one'];
say 'array ref 4: ' . ['one', 'two'];

Normally, parens just change precedence. If that were true here,

\('one', 'two')

would be equivalent to

('one', \'two')

That's because a comma/list operator in scalar context normally returns that to which its last expression evaluates. But \(...) is special-cased to be equivalent to the following more useful construct:

(\'one', \'two')

Taking a reference to an enumerated list is not the same as using square brackets--instead it's the same as creating a list of references!

@list = (\$a, \@b, \%c);
@list = \($a, @b, %c);      # same thing!

That means that

say 'array ref 4: ' . \('one', 'two');

is equivalent to

say 'array ref 4: ' . (\'one', \'two');

which is equivalent to

say 'array ref 4: ' . \'two';
ikegami
  • 367,544
  • 15
  • 269
  • 518
8

From perlref:

Taking a reference to an enumerated list is not the same as using square brackets--instead it's the same as creating a list of references!

@list = (\$a, \@b, \%c);
@list = \($a, @b, %c);      # same thing!

You get a scalar reference because the item in the list that ends up with its reference passed to the LHS is a scalar.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
3

It seems as if you expect that these are equivalent:

my @array1 = ('one', 'two');
my $array2 = \('one', 'two');

But that is not the correct syntax to get an anonymous array. You need square brackets to create an anonymous array.

my $array3 = ['one', 'two'];  # a reference to an anonymous array
my $array4 = \['one', 'two']; # a reference to a reference to an anonymous array
ikegami
  • 367,544
  • 15
  • 269
  • 518
Dan Lowe
  • 51,713
  • 20
  • 123
  • 112
  • 1
    It's not likely you'll ever need `\['one', 'two']`. – ikegami Dec 10 '15 at 15:10
  • @ikegami I agree with you on that, but the question was not about practical or real use cases, it was about how the language works, so I added that simply for illustrative purposes. – Dan Lowe Dec 10 '15 at 17:23