在Python中,如果使用越界键/索引索引集合结构,则会在面部中获得一记:
>>> [1, 2, 3][9]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
Run Code Online (Sandbox Code Playgroud)
这是一个例外; 它派生自BaseException,未能处理一个会导致我的程序崩溃,这几乎总是我想要的.
Perl 5和6的列表索引似乎并不关心越界索引:
$ 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>
Run Code Online (Sandbox Code Playgroud)
它在Perl 5中基本上是相同的,除了你没有得到返回的值,但执行继续正常.
我不明白为什么越界访问应该保持沉默.您获得该值的唯一警告可能是"未初始化"(但我们都知道它实际上意味着不存在)是当您将其赋予某些功能时.
我能以某种方式修复此问题吗?我可以实现我自己的post-circumfix索引操作符来覆盖在垃圾索引上死亡的默认操作符,但是没有办法区分未初始化的值和类型Any
.我能看到的唯一方法是检查请求的索引是否在范围内List.elems()
.
我可以使用什么(最好是简单,简单,干净,可读等)解决方案来解决这个问题?
在任何人说"是的,但变量未初始化之前,就像my $x;
!":在C中,如果你访问未分配的内存,你会得到一个段错误; 为什么我不能拥有那种安全感?
我已经将它标记为Perl和Perl 6,因为虽然我正在学习Perl 6并且这个问题的细节主要适用于6,但主要思想似乎是5和6的共同方面.
dwa*_*ing 11
Perl 6具有形状数组以在简单或多维数组上强制执行数组边界.
从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
Run Code Online (Sandbox Code Playgroud)
更多例子:
use v6;
# declare an array with four elements
my @l[4] = (1..4);
try { @l.push: 42}
say @l;
# [1 2 3 4]
Run Code Online (Sandbox Code Playgroud)
这些可以是多维的
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]]
Run Code Online (Sandbox Code Playgroud)
小智 9
这将做你想要的.
my @a is default(Failure.new('IndexError'));
@a[0] = 1;
say @a[1];
say 'alive';
output:
===SORRY!===
IndexError
Run Code Online (Sandbox Code Playgroud)
如果你想要一个堆栈跟踪,你必须运行perl6 --ll-exception
或创建自己的容器Proxy
.(这是一个错误,报告为: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/
Run Code Online (Sandbox Code Playgroud)
哦,请不要听那些想要告诉你适应Perl 6的反对者.Perl 6的全部内容是你可以修补它并根据你的意愿弯曲它.
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];
Run Code Online (Sandbox Code Playgroud)
有两种方法可以做到这一点.这是第三个.
try {
my Int:D @a;
say @a[0];
CATCH { default { say .^name } }
}
# OUTPUT«X::Method::NotFound?»
Run Code Online (Sandbox Code Playgroud)
人们可以争辩说,抛出的例外是LTA,或者这实际上应该是特殊的.但是,它确实是OP所要求的,而不是摆弄Array
Rakudo 实施的实施细节.
[既然你要求Perl5和Perl6答案,但你只得到一个Perl6答案,这是一个Perl5答案.]
您可以编写一个操作检查器,将索引操作替换为检查边界的操作(与no autovivification;
将非解除操作替换为不能自动生成的版本的操作相同).
归档时间: |
|
查看次数: |
775 次 |
最近记录: |