Как вернуть значение из фазера 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()
Есть две функции в игре.
bar()
сам метод.- Лямбда, в которую вы вложили возврат.
Это означает, что ваше возвращение неоднозначно (ну, по крайней мере, для некоторых людей), и компилятор откажется.
Без "возврата" значение в foo()
обрабатывается как константа внутри блока, и блок возвращает Nil. Это означает, что в foo()
вы фактически избежали разбора значения return
эффективно нажимая Nil
в стеке.
Вот почему у вас есть 3 Nil
s в захваченном выводе для 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
уже вернулся до того, как ваша лямбда будет вызвана в первый раз. После того, как список say
d, все значения генерируются, и генерируется исключение.
Правильный способ получить то, что вы хотите, - это вызвать.eager для результата вашей карты, таким образом вызывая оценку всего списка до возврата из функции, что позволяет вам использовать return
изменить значение, которое bar
возвращается.