Почему обе ветви, кажется, работают? - PullRequest
1 голос
/ 15 марта 2012

Я полностью сбит с толку.Вот мой код:

use strict;
use warnings;
use Test::More;

subtest 'huh?' => sub {
    my $i = 0;
    eval {
        $i++;
    } || do {
        $i++;
    };
    is($i, 1, "only execute one branch (i: $i)");
};

&done_testing();

А вот мой тестовый вывод (при запуске с ActivePerl 5.12, Mac OS X):

    not ok 1 - only execute one branch (i: 2)
    #   Failed test 'only execute one branch (i: 2)'
    #   at test.pl line 14.
    #          got: '2'
    #     expected: '1'
    1..1
    # Looks like you failed 1 test of 1.
not ok 1 - huh?
#   Failed test 'huh?'
#   at test.pl line 15.
1..1
# Looks like you failed 1 test of 1.

Что здесь происходит?Я ожидал, что запустится только первая ветка, так как ничего die s.Но похоже, что обе ветви выполнены.

Ответы [ 2 ]

5 голосов
/ 15 марта 2012

$i++ возвращает значение $i до увеличения . Так как это 0, то это ложно. И eval возвращает последний оцененный результат, который является этим ложным значением. Затем он пытается выполнить следующий блок (как и должно быть).

Если вы хотите, чтобы он занимал только первую ветвь, вам нужно сделать выражение приращения «increment, затем return», например, eval { ++$i }.

Теперь лучший способ проверить, не удалось ли eval, это не вернуть 1, а сделать следующее:

  1. локализовать $@ (или $English::EVAL_ERROR)
  2. Eval
  3. тест $@

    local $@;
    eval { $some_sub->(); };
    croak( "Failed in evaluate: $@" ) if $@;
    
2 голосов
/ 15 марта 2012

eval { $i ++ } возвращает тот же результат, что и $i ++, а именно значение, которое $i имело до приращения. Поскольку для $i установлено значение 0, возвращается 0, что ложно, что означает, что также вычисляется правый операнд ||.

Я думаю, что вы путаете результат , возвращаемый с eval (который является просто результатом содержащегося выражения) с результатом die в eval, который сохраняется в $@.

...