Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly mean the ${...} in the perl?

Tags:

arrays

perl

Thinking about the next. Have a LIST

qw(a b c);

now, assign the LIST into nameless (anonymous) ARRAY

[ qw(a b c) ]

so the next

use 5.016;
use warnings;
use diagnostics;
my $x = [ qw(a b c) ];
say ref $x;  #ARRAY - the $x is an ARRAY reference, and
say $x->[1]; #prints "b", and
say [ qw(a b c) ]->[1]; #works too

but what happens now?

use 5.016;
use warnings 'all';
use diagnostics;
say ${[ qw(a b c) ]}[1];

it prints b, but

my $y = ${[ qw(a b c) ]};

is an error,

Not a SCALAR reference at pepe line 6 (#1)
    (F) Perl was trying to evaluate a reference to a scalar value, but found
    a reference to something else instead.  You can use the ref() function
    to find out what kind of ref it really was.  See perlref.

Uncaught exception from user code:
    Not a SCALAR reference at pepe line 17.

So, whats mean the contruction ${.... }

  • It "works" in the say (prints the second element of the anonymous array), but don't understand why
  • but can't assign it into variable

And the hint from the diagnostics is not very helpful, because how I should use the ref when I can't assign? What I missed from the perlref?

like image 342
cajwine Avatar asked May 13 '13 21:05

cajwine


2 Answers

${ EXPR1 }[ EXPR2 ] is an array index dereference. It returns the element at the index returned by EXPR2 of the array referenced by the reference returned by EXPR1.

${ $array_ref }[ ... ] is to array references as $array[...] is to arrays.


${ EXPR } that's not followed by [ or { is a scalar dereference. It returns the scalar referenced by the reference returned by EXPR.

${ $scalar_ref } is to scalar references as $scalar is to scalars.


As you can see, when dealing with a reference, you can use the same syntax as you normally would, except that you replace the name of the variables with {$ref} (keeping the leading sigil).

As such, @{ $array_ref } is to array references as @array is to arrays.

say @{[ qw(a b c) ]};

This is the essence of the chart in my earlier post Mini-Tutorial: Dereferencing Syntax. See also:

  • References quick reference
  • perlref
  • perlreftut
  • perldsc
  • perllol

Oops, I thought you had

say ${[ qw(a b c) ]};   # Want to print a b c

You have

my $y = ${[ qw(a b c) ]};

You want

my $y = [ qw(a b c) ];

[] creates an array and a reference to that array, and returns the latter, kinda like

my $y = do { my @anon = qw(a b c); \@a };
like image 154
ikegami Avatar answered Oct 27 '22 07:10

ikegami


Given an array @arr and an arrayref $aref = \@arr, then inside the following groups of expressions all lines are equivalent:

Accessing the whole array:

@ arr
@{$aref}

Accessing a single scalar in the array:

$ arr   [$i]
${$aref}[$i]
$ aref->[$i]

Accessing a slice of entries:

@ arr   [$i .. $j]
@{$aref}[$i .. $j]

(the spaces are included for alignment and are not recommended for actual code).

The ${}, @{}, … are circumfix dereference operators. However, accessing a single scalar changes the sigil from % or @ to $. Without references, this makes total sense. With them, it's just slightly complicated, until you read perlreftut (esp. the two reference usage rules).

like image 32
amon Avatar answered Oct 27 '22 07:10

amon