print join ', ', 1..$#F; # 1, 2, 3, 4, 5, 6, ...
print join ', ', 1..-1; #
The reason for this is that the '..
' operator doesn't do anything special inside of an array subscript.
In list context, it returns a list of values counting (up by ones) from the left value to the right value. If the left value is greater than the right value then it returns the empty list.
$#F
is the index of the last element, which is the same as the length minus one '@F -1
'. ( If the length is at least one. )
$F[-1]
is just a special case, to make it easier to get at elements from the other end, without having to calculate the position manually.
$F[-1] === $F[ @F -1 ] === $F[ $#F ]
@F[ 1 .. (@F -1) ] === @F[ 1 .. $#F ]
@F[ 1 .. (@F -2) ] === @F[ 1 .. ( $#F -1 ) ]
Knowing this you can use variables in a range operator:
use strict;
use warnings;
use feature 'say';
sub list{
my($arr,$first,$last) = @_;
$first = @$arr + $first if $first < 0;
$last = @$arr + $last if $last < 0;
return @$arr[ $first .. $last ];
}
my @F = 1..3;
say join ', ', list(\@F,1,-1)
2, 3
Note: this is an incomplete example, it won't work correctly for some edge cases