Как заставить perl6 умереть на неопределенных значениях?

Я пытаюсь работать с хэшем в Perl6, но когда я в него (намеренно) добавляю некоторые поддельные значения, такие как

say %key<fake_key>;

я получаю

(Any)

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

Например,

#!/usr/bin/env perl

use strict;
use warnings 'FATAL' => 'all';
use autodie ':all';

my %hash;
print "$hash{y}\n";

с 5.26.1 производит

Use of uninitialized value $hash{"y"} in concatenation (.) or string at undefined.pl line 8.
Command exited with non-zero status 255

Как я могу получить эквивалент use warnings 'FATAL' => 'all' и use autodie qw(:all) в Perl6?

Ответ 1

Aiui ваш вопрос:

I'm looking for use autodie qw(:all) & use warnings 'FATAL' => 'all' in Perl6

Эквивалент autodie в P6

Aiui use autodie qw(:all) в P5 становится use fatal; в P6. Это лексически ограниченный эффект.

Раздел autodie в руководстве по скорлупе P5-P6 объясняет, что процедуры теперь возвращают Failure, чтобы указать на ошибки.

Прагма fatal заставляет возвращать Failure из подпрограммы автоматически генерировать исключение, содержащее Failure. Если вы не предоставите код, который их перехватит, эти исключения, заключающие в оболочку Failure, автоматически исчезнут.

Эквивалент use warnings 'FATAL' в P6

Aiui use warnings 'FATAL' => 'all' в P5 становится CONTROL { when CX::Warn { note $_; exit 1 } } в P6. Это лексически ограниченный эффект.

CONTROL Исключения объясняют, как они работают.

Исключения CONTROL - это подмножество всех исключений, которые по умолчанию .resume d - программа остается в живых по умолчанию, когда их выдают.

Приведенный мною код P6 (который взят из Как я могу сделать все предупреждения фатальными?, на который вы ссылались) вместо этого приводит к смерти исключений CONTROL (из-за exit рутина).

Возвращаясь к текущему тексту вопроса:

say %key<fake_key>; # (Any)

Я хочу, чтобы программа умерла в таких случаях...

Используйте либо ответ Jonathan++ (используйте put, который, в отличие от say, не пытается поддерживать вашу программу)), либо ответ Scimon++ KeyRequired, который сделает доступ к несуществующему ключу фатальным.

... as Perl5 does...

Только если вы используете use warnings 'FATAL' ..., так же, как P6, если вы используете эквивалент.

... потому что это означает, что важные данные отсутствуют.

Часто это означает, что неважные данные отсутствуют или даже важные данные, которые вы не хотите, определяли в течение некоторого времени, когда вы пытаетесь получить к ним доступ, поэтому Perls по умолчанию поддерживает вашу программу в живых и требует, чтобы вы указали ей то, что вы хотите, если вам что-то нужно отличается.

Вы можете использовать вышеупомянутые конструкции, чтобы получить точный желаемый результат, и они будут ограничены данной переменной (если вы используете роль KeyRequired) или оператором (используя put вместо say) или лексической областью действия ( используя прагму или блок CONTROL).

Ответ 2

Вы можете создать роль для этого. Простая версия будет:

role KeyRequired { 
    method AT-KEY( \key ) { 
        die "Key {key} not found" unless self.EXISTS-KEY(key); 
        nextsame; 
    } 
};

Затем вы создаете свой хеш с помощью: my %key does KeyRequired; и он умрет, если вы запросите несуществующий ключ.

Ответ 3

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

my %key;
print "%key<fake_key>\n"; # Gives a warning

Или, более аккуратно, используйте put:

my %key;
put %key<fake_key>;

Подпрограмма put ("печать с использованием терминатора") будет приводить к строковому значению, что вызывает предупреждение об использовании неопределенного значения в строковом контексте.

В отличие от этого, say не .gist, а вместо этого вызывает .gist для объекта и печатает все, что возвращает. В случае неопределенного значения, суть его - это имя его типа, заключенное в скобки. В общем, say - который использует .gist внизу - дает больше информации. Например, рассмотрим массив:

my @a = 1..5;
put @a;          # 1 2 3 4 5
say @a;          # [1 2 3 4 5]

Где put просто соединяет элементы с пробелами, но, say представляет структуру и, что это массив.

Ответ 4

Простой ответ - не использовать say.

say %key<fake_key>;
# (Any)

put %key<fake_key>;
# Use of uninitialized value of type Any in string context.
# Methods .^name, .perl, .gist, or .say can be used to stringify it to something
# meaningful.
#   in block <unit> at <unknown file> line 1

say звонки .gist который печатает достаточно информации для человека, чтобы понять, что было напечатано.
put просто пытается превратить его в Str и вывести его, но в этом случае выдает ошибку.

Ответ 5

Добавить //die после каждого использования:

say %key<fake_key> // die;