use 5.016;
use warnings "all";
use Data::Dumper;
my @abc = (1, 2, 3);
my @bbb = @abc[1..2];
my @ccc = @abc[1...2];
my @ddd = @abc[1....2];
say Dumper "@bbb"; # output: '2 3'
say Dumper "@ccc"; # output: '2 3'
say Dumper "@ddd"; # output: ''
Why is there no syntax error in code above?
What do 1...2
(three dots) and 1....2
(four dots) mean here?
0
2 Answers
1..2
is tokenized as 1
..
2
, and parsed as a range operator with two integer constant operands. When evaluated, it is evaluated in list context, and it produces the integers from 1 to 2 inclusive.
1...2
is tokenized as 1
...
2
, and parsed as a range operator with two integer constant operands. ...
is different than ..
in scalar context, but they’re the same in list context.
1....2
is tokenized as 1
...
.2
, and parsed as a range operator with two constant operands. When evaluated, it is evaluated in list context, and it produces the integers from 1 to 0.2 inclusive, which is to say it produces nothing.
A side note:
When tokenizing, Perl normally gobbles up as many characters as it can with no regard as to what follows. One exception is that a .
will never be included in a numeric literal if followed by another .
.
This means that 1..2
is always tokenized as 1
, ..
, 2
and never 1.
.2
or 1.
.
2
.
This means that 1...2
is always tokenized as 1
, ...
, 2
and never 1.
, ..
, 2
or 1
, ..
, .2
.
This also means that 1.....2
will never be tokenized as 1.
...
.2
even though that would prevent the parser from throwing a syntax error.
(Thanks @Dada for helping me correct this.)
A side note:
At least some constant ranges are flattened into an array constant.
1..2
in list context and 1...2
in list context both compile to a two-element array constant, just like 1, 2
.
1....2
in list context compiles to an empty array constant.
0
If you give Perl the option -MO=Deparse
it will say how Perl parse your code.
The three-dot form (1...2)
parses as (1..2)
. This is unexpected to me, but I assume it is a side effect of being able to parse both the two-dot and three-dot forms of the flip-flop operator.
The four-dot form parses as (1 .. .2)
. This is an empty range, so your array slice is also empty.
1
-
Re "The three-dot form (1…2) parses as (1..2).", No. They are parsed differently, but they compile to the same the thing in this case. Specifically, they compile to a constant array of two elements, just like
1, 2
. /// Re "it will say how Perl parse your code.", Deparse is a decompiler. It can help show how Perl understand codes, but it doesn't actually show how code is parsed. That's why1..2
,1...2
and1, 2
all Deparse as1, 2
. (They don't Deparse as1..2
as you claim.)– ikegami5 hours ago