Reputation: 607
Suppose num is an array,
@num = (1 .. 10);
To find its length we use the following expression,
$num = @num;
Then I used the same $num
in the assignment below.
@slicenum = $num[1 .. 6];
I was aware that for slicing an array we use @num
instead of $num
. It ran well without throwing any errors. But when I print the value of @slicenum
, it gave me 2 as a result.
@slicenum = $num[1 .. 6, 10 .. 20];
For the above assignment, I got 1 as a result.
Although the value of $num
remains 10, please explain what is happening in the above two assignments.
Upvotes: 2
Views: 179
Reputation: 67900
You have discovered a bit of Perl magic at work. The range operator (aka the flip-flop operator as amon points out) ..
in this scalar context seems to want to compare the range to $.
, which it does when used with integers:
$ perl -lwe '@a = 1..10; @foo = $a[1..6]; print @foo'
Use of uninitialized value $. in range (or flip) at -e line 1.
Argument "" isn't numeric in array element at -e line 1.
1
$ perl -lwe '$x=<>; @a = 1..10; @foo = $a[1..6]; print @foo' somefile.txt
Name "main::x" used only once: possible typo at -e line 1.
2
As darch mentions, $a[1 .. 6]
imposes a scalar context to the expression inside the subscript: [ EXPR ]
. As opposed to when using @a[1 .. 6]
, where a list context is imposed instead.
So, this part:
1 .. 6
In scalar context means if ($. >= 1 and $. <= 6)
When the $.
is uninitialized, it returns undef
(which evaluates to 0
in numeric context) and emits the uninitialized warning. When $.
is not uninitialized (i.e. when a file has been opened and read somewhere previously in the program) it returns either true or false, or in this case 1
or the empty string. In your case, it seems to return 1
, which then results in
$num[1 .. 6]
..evaluating to
$num[1]
Which in return returns element number 1, which is 2
.
So, in short: The statement 1 .. 6
has a different meaning depending on context. In list context, it returns 1,2,3,4,5,6
, that is, a range of integers. In scalar context, it returns true (1
) if the $.
(line count) variable is between 1 or 6, otherwise returns false (empty string).
Here is the mention of this phenomena in the documentation:
In list context, it returns a list of values counting (up by ones) from the left value to the right value.
[ ... ]
In scalar context, ".." returns a boolean value. The operator is bistable, like a flip-flop, and emulates the line-range (comma) operator of sed, awk, and various editors.
Upvotes: 10