In Python, if you index a collection structure with a out-of-bounds key/index, you get a slap in the face:
>>> [1, 2, 3][9]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
That's an Exception; it derives from BaseException, and failing to handle one will crash my program, which is almost always what I want.
Perl 5 and 6's list indexing seems to not care about out-of-bounds indexing:
$ perl6
> my @l = (1..4);
[1 2 3 4]
> say @l[2];
3
> say @l[9];
(Any)
> print @l[9];
Use of uninitialized value @l of type Any in string context
<snip>
True
> my $x = @l[9]; # even assignment doesn't error! who decided this was okay!?
> say $x; print $x;
(Any)
Use of uninitialized value $x of type Any in string context
<snip>
it's basically the same thing in Perl 5, except you don't get a value returned, but execution continues as normal.
I don't understand why out-of-bounds accessing should ever be silent. The only warnings you get that value may be "uninitialised" (but we all know it really means non-existent) are when you give it to certain functions.
Can I fix this somehow? I could implement my own post-circumfix indexing operator to override the default one that dies on junk index, but there's no way to tell the difference between an uninitialised value and the type Any
. The only way to do that I can see is to check if the requested index is in the range List.elems()
.
What (preferably minimal, simple, clean, readable, etc) solution can I use to remedy this?
Before anyone says "yes, but the variable is uninitialised, like my $x;
!": in C you get a segfault if you access memory you didn't allocate; why can't I have that sort of safety?
I've tagged this as both Perl and Perl 6 because, while I'm learning Perl 6 and the particulars of this question apply mostly to 6, the main idea seems to be a shared aspect of both 5 and 6.
Perl 6 has shaped arrays to enforce array bounds on simple or multidimensional arrays.
From S09:
my int @ints[4;2]; # Valid indices are 0..3 ; 0..1
my @calendar[12;31;24]; # Valid indices are 0..11 ; 0..30 ; 0..23
Some more examples:
use v6;
# declare an array with four elements
my @l[4] = (1..4);
try { @l.push: 42}
say @l;
# [1 2 3 4]
These can be multi-dimensional
my @tic_tac_toe[3;3] = <x o x>, <o . o>, < x o x>;
@tic_tac_toe[1;1] = "x"; # ok
try @tic_tac_toe[3][3] = "o"; # illegal
say @tic_tac_toe;
# [[x o x] [o x o] [x o x]]
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