Consider:
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 aren't there any syntax errors in the code above?
What do 1...2
(three dots) and 1....2
(four dots) mean here?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With