Как вернуть значение из фазера CATCH блока?

Каков синтаксис для возврата значения из фазера CATCH из блока, который не является процедурой?

sub foo() {
    <1 2 3>.map: -> $a {
        die 'oops';
        CATCH { default { 'foo' } }
    }
}

sub bar() {
    <1 2 3>.map: -> $a {
        die 'oops';
        CATCH { default { return 'bar' } }
    }
}

say foo(); # (Nil, Nil, Nil)
say bar(); # Attempt to return outside of immediatelly-enclosing Routine (i.e. `return` execution is outside the dynamic scope of the Routine where `return` was used)

редактировать: желаемый результат:

say baz(); # (baz baz baz)

Вариант использования mapв Seq с методом, который периодически генерирует исключение, обрабатывая исключение в блоке, переданном в map, возвращая значение по умолчанию.

2 ответа

Возврат выходов из области действия функции, но способ, которым вы используете его в bar() Есть две функции в игре.

  1. bar() сам метод.
  2. Лямбда, в которую вы вложили возврат.

Это означает, что ваше возвращение неоднозначно (ну, по крайней мере, для некоторых людей), и компилятор откажется.

Без "возврата" значение в foo() обрабатывается как константа внутри блока, и блок возвращает Nil. Это означает, что в foo() вы фактически избежали разбора значения returnэффективно нажимая Nil в стеке.

Вот почему у вас есть 3 Nils в захваченном выводе для foo(), За bar() неясно, если вы хотели прекратить выполнение bar() рутина на первое выброшенное исключение или если вы просто хотели пройти 'bar' назад как неNil значение блока CATCH, помещенного в стек.

Слегка измененная версия вашего кода

#!/bin/env perl6

sub foo() {
    <1 2 3>.map: -> $a {
        die 'oops';
    }
    CATCH { default { 'foo' } }
}

sub bar() {
    <1 2 3>.map: -> $a {
        die 'oops';
    }
    CATCH { default { return 'bar' } }
}

say foo();

say bar();

может сделать это немного яснее. Это вывод

[edwbuck@phoenix learn_ruby]$ ./ed.p6 
Nil
bar

Здесь происходит то, что ленивые списки делают поток управления неочевидным.

Возвращаемым значением обеих ваших функций является Seq, значения которого генерируются путем вызова маленькой лямбды для значений a, b и c по очереди. Зная это, легко понять, почему вы не можете изменить возвращаемое значение bar: bar уже вернулся до того, как ваша лямбда будет вызвана в первый раз. После того, как список sayd, все значения генерируются, и генерируется исключение.

Правильный способ получить то, что вы хотите, - это вызвать.eager для результата вашей карты, таким образом вызывая оценку всего списка до возврата из функции, что позволяет вам использовать return изменить значение, которое bar возвращается.

Другие вопросы по тегам