1

我正在编写新的 Perl 5 模块Class::Tiny::ConstrainedAccessor以在您触摸对象属性时通过设置或获取默认值来检查类型约束。我正在编写单元测试并希望为后一种情况运行访问器。但是,我担心 Perl 可能会优化我的访问器函数调用,因为返回值被丢弃了。会吗?如果是这样,我可以告诉它不要吗?是否记录了相应的行为?如果答案像“别担心”一样简单,那已经足够了,但是对文档的引用将不胜感激:)。

当我在 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

这个问题涉及变量,但不涉及函数。 perlperf说 Perl 会优化掉各种东西,但是除了()原型函数之外,我不清楚是什么。

在 JavaScript 中,我会说void obj.accessor();,然后我肯定会知道它会运行,但结果会被丢弃。但是,我不能undef $obj->accessor;用于类似的效果;编译合法地失败了Can't modify non-lvalue subroutine call of &Klass::accessor.

4

1 回答 1

1

Perl 永远不会优化掉子调用,并且不应该在任何语言中优化掉带有副作用的子调用。

undef $obj->accessor意味着类似于$obj->accessor = undef

于 2019-03-14T15:03:25.877 回答