Нужно ли указывать компилятору Perl не оптимизировать вызовы функций без игнорируемых возвращаемых значений? - PullRequest
1 голос
/ 14 марта 2019

Я пишу новый модуль Perl 5 Class :: Tiny :: ConstrainedAccessor для проверки ограничений типов при касании атрибутов объекта, либо путем установки, либо путем получения значения по умолчанию.Я пишу модульные тесты и хочу запустить средства доступа для последнего случая.Однако я обеспокоен тем, что Perl может оптимизировать мой вызов функции доступа, поскольку возвращаемое значение отбрасывается.Будет ли он?Если так, могу я сказать, что нет?Задокументировано ли соответствующее поведение?Если ответ так же прост, как «не беспокойтесь об этом», это достаточно хорошо, но ссылка на документы была бы полезна :).

Следующий MCVE успешно выполняется, когда я запускаю его на своем Perl 5.26.2 x64 Cygwin.Тем не менее, я не знаю, гарантировано ли это, или это только сейчас работает и может когда-нибудь измениться.

use 5.006; use strict; use warnings; use Test::More; use Test::Exception;

dies_ok {   # One I know works
    my $obj = Klass->new;   # Default value of "attribute" is invalid
    diag $obj->accessor;    # Dies, because the default is invalid
} 'Bad default dies';

dies_ok {
    my $obj = Klass->new;
    $obj->accessor;         # <<< THE QUESTION --- Will this always run?
} 'Dies even without diag';

done_testing();

{   package Klass;
    sub new { my $class = shift; bless {@_}, $class }
    sub check { shift; die 'oops' if @_ and $_[0] eq 'bad' }
    sub default { 'bad' }
    sub accessor {
        my $self = shift;
        if(@_) { $self->check($_[0]); return $self->{attribute} = $_[0] }   # W
        elsif(exists $self->{attribute}) { return $self->{attribute} }      # R
        else {  
            # Request to read the attribute, but no value is assigned yet.
            # Use the default.
            $self->check($self->default);    # <<<---- What I want to exercise
            return $self->{attribute} = $self->default;
        }
    } #accessor()
} #Klass

Этот вопрос касается переменных, но не функций. perlperf говорит, что Perl оптимизирует различные вещи, но кроме () -прототипированных функций, мне не ясно, что.

В JavaScript я бы сказал void obj.accessor();, итогда я бы точно знал, что он будет работать, но результат будет отброшен.Однако я не могу использовать undef $obj->accessor; для аналогичного эффекта;компиляция законно завершается с Can't modify non-lvalue subroutine call of &Klass::accessor.

1 Ответ

1 голос
/ 14 марта 2019

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

undef $obj->accessor означает что-то похожее на $obj->accessor = undef

...