Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I please have an ArrayOutOfBoundsException?

Tags:

perl

raku

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.

like image 223
cat Avatar asked Jan 27 '16 03:01

cat


1 Answers

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]]
like image 179
dwarring Avatar answered Sep 28 '22 07:09

dwarring