Why does perl only look up the last index when using the range operator?

I have an array, @array , of @array references. If I use the range operator to print elements 1 to 3 from @array , print @array[1..3] , perl prints array references for elements 1 to 3.

Why, when I try to dereference array references indexed between 1 and 3, @{@array[1..3]} perl only @{@array[1..3]} and display the last element indexed in the range statement?

Is there a way to use the range operator when dereferencing an array?

Code example

 #!/bin/perl use strict; use warnings; my @array = (); foreach my $i (0..10) { push @array, [rand(1000), int(rand(3))]; } foreach my $i (@array) { print "@$i\n"; } print "\n\n================\n\n"; print @{@array[1..3]}; print "\n\n================\n\n"; 
+6
source share
4 answers

@{@array[1..3]} is a weird looking construct. @{ ... } is an array dereference operator. He needs a link, which is a type of scalar. But @array[ ... ] creates a list.

This is one of those situations where you need to remember a rule to evaluate a list in a scalar context. The rule says that there is no general rule. Each list operator does its job. In this case, apparently, the array slice operator used in a scalar context returns the last element of the list. @array[1..3] in the scalar context is the same as $array[3] .

As you noticed, this is not useful. Array segments are not intended for use in a scalar context

If you want to smooth the 2-dimensional structure of nested arrays into a 1-dimensional list, use map :

 print join ' ', map { @$_ } @array[1..3] 

You are still using the range operator for slicing. You just need some kind of loop construct (e.g. map ) to apply the array explode operator separately to each element of the external array.

+3
source

From perldata :

Slices in a scalar context return the last slice element.

@{ ... } separates the scalar value as an array, which means that the dereferenced value is in a scalar context. From the quotation of perldata above, we know that this will return the last element. Therefore, the result is the last element.

A more reasonable approach would be to iterate over your slice and print each link to a separate array:

 use strict; use warnings; use feature qw(say); my @array_of_arrayrefs = ( [qw(1 2 3)], [qw(4 5 6)], [qw(7 8 9)], [qw(abc)], ); foreach my $aref ( @array_of_arrayrefs[1..3] ) { say join ',', @$aref; } 
+5
source

The @{ ... } construct looks for a scalar code value in curly braces as an array

I donโ€™t understand what you expect from @{ @array[1..3] } , but the list @array[1..3] in a scalar context returns only the last element of the list - $array[3] - so you request @{ $array[3] } , which I think is what you got

If you explain what you want to print, I'm sure we can help, but dereferencing a list makes little sense.

+1
source

@array[1..3] - a list of 3 references to the array. You cannot dereference them all at once, so you must iterate over this list and dereference each element separately:

 print @$_ for @array[1..3]; print "@$_\n" for @array[1..3]; # for better looking output 
+1
source

All Articles