是否需要告诉 Perl 编译器不要优化带有忽略 return 值的函数调用?
Does the Perl compiler need to be told not to optimize away function calls with ignored return values?
我正在编写新的 Perl 5 模块 Class::Tiny::ConstrainedAccessor 以在您触摸对象属性时通过设置或获取默认值来检查类型约束。我正在编写单元测试并希望 运行 后一种情况的访问器。但是,我担心 Perl 可能会优化我的访问器函数调用,因为 return 值被丢弃了。会吗?如果是这样,我可以告诉它不要吗?是否记录了相应的行为?如果答案像 "don't worry about it," 一样简单,那就足够了,但如果能参考一下文档,我们将不胜感激 :) .
当我在我的 Perl 5.26.2 x64 Cygwin 上 运行 以下 MCVE 成功。但是,我不知道这是否有保证,或者它是否恰好现在有效并且可能有一天会改变。
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
deals with variables, but not functions. perlperf 说 Perl 会优化各种东西,但除了 ()
-原型函数,我不清楚是什么。
在JavaScript中,我会说void obj.accessor();
,然后我肯定会知道它会运行,但结果会被丢弃。但是,我不能使用 undef $obj->accessor;
来达到类似的效果;编译合法地失败并显示 Can't modify non-lvalue subroutine call of &Klass::accessor
.
Perl 永远不会优化掉子调用,任何语言都不应该优化掉有副作用的子调用。
undef $obj->accessor
意思类似于 $obj->accessor = undef
我正在编写新的 Perl 5 模块 Class::Tiny::ConstrainedAccessor 以在您触摸对象属性时通过设置或获取默认值来检查类型约束。我正在编写单元测试并希望 运行 后一种情况的访问器。但是,我担心 Perl 可能会优化我的访问器函数调用,因为 return 值被丢弃了。会吗?如果是这样,我可以告诉它不要吗?是否记录了相应的行为?如果答案像 "don't worry about it," 一样简单,那就足够了,但如果能参考一下文档,我们将不胜感激 :) .
当我在我的 Perl 5.26.2 x64 Cygwin 上 运行 以下 MCVE 成功。但是,我不知道这是否有保证,或者它是否恰好现在有效并且可能有一天会改变。
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
()
-原型函数,我不清楚是什么。
在JavaScript中,我会说void obj.accessor();
,然后我肯定会知道它会运行,但结果会被丢弃。但是,我不能使用 undef $obj->accessor;
来达到类似的效果;编译合法地失败并显示 Can't modify non-lvalue subroutine call of &Klass::accessor
.
Perl 永远不会优化掉子调用,任何语言都不应该优化掉有副作用的子调用。
undef $obj->accessor
意思类似于 $obj->accessor = undef