Can I please have an ArrayOutOfBoundsException?

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]]

This will do what you want.

my @a is default(Failure.new('IndexError'));
@a[0] = 1;
say @a[1];
say 'alive';

output:

===SORRY!===
IndexError

If you want a stacktrace you either have to run perl6 --ll-exception or create your own container with Proxy. (This is a bug, reported as: RT#127414)

see: https://doc.perl6.org/type/Failure
see: https://doc.perl6.org/routine/is%20default
see: https://perl6advent.wordpress.com/2015/12/02/day-2-2-bind-or-2-bind/

Oh, and please don't listen to the naysayers who want to tell you to adapt to Perl 6. The whole point of Perl 6 is that you can mend it and bend it to your will.

class NonvivArray is Array {
    multi method AT-POS(NonvivArray:D: Int:D $pos) is raw {
        say 'foo';
        my $val = callsame;
        X::OutOfRange.new(got=>$pos, range=>0..self.elems-1).throw unless $val;
        $val;
    }

    multi method AT-POS(NonvivArray:D: int $ipos) is raw {
        say 'foo';
        my $val = callsame;
        X::OutOfRange.new(got=>$ipos, range=>0..self.elems-1).throw unless $val;
        $val;
    }
}

my NonvivArray $a;
$a.push: 1;
dd $a;
say $a[1];

There is more then two ways to do it. Here is the third.

try { 
    my Int:D @a; 
    say @a[0]; 
    CATCH { default { say .^name } } 
}
# OUTPUT«X::Method::NotFound␤»

One can argue that the exception thrown is LTA or that this should actually be special cased. However, it does what the OP asked for without fiddling with implementation details of Array as implemented by Rakudo.


[Since you asked for both a Perl5 and a Perl6 answer, but you only got a Perl6 answer, here's a Perl5 answer.]

You could write an op checker that replaces the indexing ops with ones that check bounds (in the same way that no autovivification; replaces dereferencing ops with versions that don't autovivify.)

Tags:

Perl

Raku