Praveen kumar
Praveen kumar

Reputation: 607

How does the assignment operator (=) in Perl work internally?

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

Answers (1)

TLP
TLP

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

Related Questions