Problem with syntax getting array elements

D

Dave Saville

Given

my @x = qw(a b c);
print "$x[2]\n";
($a, $b) = @x[1,2];
print "$a $b\n";

Gives me

c
b c

But

my %h;
$h{a} = [1,2,3];
print $h{a}[2]."\n";
my ($a, $b) = $h{a}[1,2];
print "$a $b\n";

Gives

3
Use of uninitialized value $b in concatenation (.) or string
3

I have tried all sorts of brackets braces etc. in various combinations
but I cannot get the anonymous array contained in the hash to work
like the first example. What silly thing am I missing?

TIA
 
T

Tim Watts

Dave said:
Given

my @x = qw(a b c);
print "$x[2]\n";
($a, $b) = @x[1,2];
print "$a $b\n";

Gives me

c
b c

But

my %h;
$h{a} = [1,2,3];
print $h{a}[2]."\n";
my ($a, $b) = $h{a}[1,2];
print "$a $b\n";

Gives

3
Use of uninitialized value $b in concatenation (.) or string
3

I have tried all sorts of brackets braces etc. in various combinations
but I cannot get the anonymous array contained in the hash to work
like the first example. What silly thing am I missing?

TIA

my %h;
$h{a} = [1,2,3];
print $h{a}->[2]."\n"; #[1]
my ($a, $b) = @{$h{a}}[1,2]; #[2]
print "$a $b\n";

[1] As the value of $h{a} is an array ref, not an array, I prefer to use the
deref operator -> for clarity.

[2] This defrefs the arrayref explicitly.

I am not a syntax master so I will not attempt to explain the ins and outs,
but the above works I think as you intended...

HTH

Tim
 
D

Dave Saville

[1] As the value of $h{a} is an array ref, not an array, I prefer to use the
deref operator -> for clarity.

[2] This defrefs the arrayref explicitly.

I am not a syntax master so I will not attempt to explain the ins and outs,
but the above works I think as you intended...

Thank you very much. I had tried -> but not the same way. I knew it
was something like that but could not figure it out nor find any
helpful example.
 
U

Uri Guttman

DS> On Wed, 6 Jun 2012 09:01:26 UTC, Tim Watts <[email protected]>
DS> wrote:

DS> said:
[1] As the value of $h{a} is an array ref, not an array, I prefer to use the
deref operator -> for clarity.

[2] This defrefs the arrayref explicitly.

I am not a syntax master so I will not attempt to explain the ins and outs,
but the above works I think as you intended...

DS> Thank you very much. I had tried -> but not the same way. I knew it
DS> was something like that but could not figure it out nor find any
DS> helpful example.

you use -> to get only one element from a ref. it is clearer to use ->
for this purpose. when you want to slice (getting multiple elements) you
must do a full deref of the ref with @{} or %{} followed by the normal
slice index (e.g. [1, 2]).

uri
 
R

Rainer Weikusat

Dave Saville said:
my %h;
$h{a} = [1,2,3];
print $h{a}[2]."\n";
my ($a, $b) = $h{a}[1,2];

The reason why this doesn't work is because the expression inside the
subscript ([]) is evaluated in scalar context in this case,
consequently, it's a comma-operator expression whose value is 2. In
order to denote a slice, a @ is needed in here.

$h{a}[1,2]

is 'syntactic sugar' for

$h{a}->[1,2]

which is, in turn, syntactic sugar for

${$h{a}}[1,2]

but since you want an array slice, it should be
(as Tim Watts already posted)

@{$h{a}}[1,2]

{{$h{a}} being a block which returns a reference of 'a suitable type'
for this expression.

If being unsure how perl 'sees' a specific expression, the Deparse
module can sometimes be helpful. For your code above, the output (perl
-MO=Deparse) is

my %h;
$h{'a'} = [1, 2, 3];
print $h{'a'}[2] . "\n";
my($a, $b) = $h{'a'}['???', 2];
print "$a $b\n";
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top