Нужно ли указывать компилятору Perl не оптимизировать вызовы функций без игнорируемых возвращаемых значений?
Я пишу новый модуль Perl 5 https://github.com/cxw42/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 ответ
Perl никогда не оптимизирует дополнительные вызовы, и дополнительные вызовы с побочными эффектами не следует оптимизировать ни на одном языке.
undef $obj->accessor
означает что-то похожее на $obj->accessor = undef