2016-01-27 3 views
5

В Python, если индекс коллекции структура с ключом/индексом недоступных, вы получите пощечину:Могу ли я получить ArrayOutOfBoundsException?

>>> [1, 2, 3][9] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
IndexError: list index out of range 

Это исключение; это происходит из 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>  

это в основном то же самое в Perl 5, за исключением того, вы не получите значение но выполнение продолжается как обычно.

Я не понимаю, почему доступ за пределы доступа должен когда-либо быть silent. Единственные предупреждения, которые вы получаете, могут быть «неинициализированы» (но мы все знаем, что это действительно означает, что не существует), когда вы передаете его определенным функциям.

Могу ли я это исправить? Я мог бы реализовать свой собственный оператор индексирования после обхода, чтобы переопределить значение по умолчанию, которое умирает на индекс нежелательной почты, но нет возможности рассказать разницу между неинициализированным значением и типом Any. Единственный способ сделать это: I может видеть, чтобы проверить, находится ли запрошенный индекс в диапазоне List.elems().

Какое (желательно минимальное, простое, чистое, читаемое и т. Д.) Решение можно использовать, чтобы исправить это?


Перед кем говорит «да, но переменная неиницализированные, как my $x;!»: В C вы получаете Segfault, если доступ к памяти, вы не выделять; почему я не могу иметь такую ​​безопасность?


Я помечено это и как Perl и Perl 6, потому что, в то время как я учусь Perl 6 и подробные сведения этого вопроса применяются в основном до 6, основная идея, как представляется, общий аспект как 5 и 6.

+0

Ошибка сегментации в C лучше, чем выполнение продолжается, как будто ничего не произошло. – cat

+2

Perl делает то, что вы просите у него, несмотря ни на что. Предполагается, что вы знаете, о чем вы просите, ну это на самом деле не предполагает ничего. Это действительно не могло дать летающий прыжок, если вы знаете или хотите, что вы просите его, это просто даст вам это. Если вы проверите «если определено», вам не нужно использовать исключения, такие как костыли. В основном это сдвиг парадигмы и являющийся разработчиком python. В этой статье довольно четко изложены различия мнений: http://yosefk.com/blog/what-makes-cover-up-preferable-to-error-handling.html – scrappedcola

+0

@scrappedcola Спасибо за ответ! Я знаю, вы можете сказать, что я полна питонизмов, но я не могу думать о каком-либо другом языке, где это не вызовет крушения, просто потому, что нет никакой другой логической реакции. – cat

ответ

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 

еще несколько примеров:

use v6; 
# declare an array with four elements 
my @l[4] = (1..4); 
try { @l.push: 42} 
say @l; 
# [1 2 3 4] 

Они могут быть многомерными

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

, если это так, так оно и есть. – cat

-1

, который почти всегда то, что я хочу.

Пожалуйста, не пытайтесь адаптировать язык к своим идеям, но приспосабливайте свои идеи к языку. Если вы не хотите этого делать, используйте другой язык, который соответствует вашим идеям. Плохая идея - попытаться написать код стиля Java в Perl так же, как писать код на Perl в Java.

+5

«Не пытайтесь адаптировать язык к своим идеям», извините, причина, по которой я программирую, - это адаптировать компьютер к моим идеям, и причина, по которой я думаю, что Perl 6 классный, потому что он податливый и адаптируется к моим идеям. – cat

+1

@cat: «... основная идея - общая ошибка/особенность как 5, так и 6». - очевидно, вы жалуетесь на язык и не приспосабливаетесь к идеям языка. Что вы считаете недостатком, то другие считают особенность. –

+0

Я только добавил этот комментарий из-за [этой вещи] (http://meta.stackoverflow.com/questions/315419/should-perl6-questions-be-tagged-with-the-perl-tag-as-well) и потому что я искренне не был уверен, было ли это поведение преднамеренным, ошибка или если я прищурился. – cat

5

[Так как вы просили как в Perl5 и ответ Perl6, но вы только получили ответ Perl6, вот ответ Perl5.]

Вы можете написать публицистическую шашку, заменяющую индексацию оп с тех, которые проверяют (так же, как no autovivification; заменяет операции разыменования с версиями, которые не автогенерируются.)

+0

'Не знаю, как 'нет автовивитации 'just yet' – cat

+0

Это похоже на идеальный ответ, если Ракудо знал, как «не автовивитировать» – cat

+2

Я не знал, что Rakudo может запустить Perl5. – ikegami

9

Это сделает то, что вы хотите.

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

output: 

===SORRY!=== 
IndexError 

Если вы хотите StackTrace вы либо должны запустить 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/ 

О, и, пожалуйста, не слушайте скептиков, которые хотят, чтобы сказать вам, чтобы адаптироваться к 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]; 

Существует более двух способов сделать это. Вот третий.

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

Можно утверждать, что исключение выбрано LTA или что это действительно должно быть специально обсажено. Тем не менее, он делает то, о чем попросил ОП, не вдаваясь в подробности реализации Array, реализованный Ракудо.

+1

Прохладный! это больше того, что я искал! Теперь, могу ли я, например, определить тип, который наследуется от «List» и который по умолчанию «Failure.new» («IndexError»), поэтому мне просто нужно написать «мой SafeList @a;» вместо этого? – cat

+3

Я добавил подкласс в Array. Я не утверждаю, что знаю, что делаю. Это скорее всего ударит вам в лицо, как только вы будете использовать бесконечные списки и/или обещания (которые являются бесконечными списками, пока они не будут). То, что вы можете сгибать Perl 6 по своему желанию, не означает, что он не укусит вас. –

+3

Я прочитал и настоящим принимаю все условия Лицензионного соглашения с пользователем ненадежного программного обеспечения – cat

Смежные вопросы