【问题标题】:Does the Perl compiler need to be told not to optimize away function calls with ignored return values?是否需要告诉 Perl 编译器不要优化带有忽略返回值的函数调用?
【发布时间】:2019-03-14 14:09:29
【问题描述】:

我正在编写新的 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

This question 处理变量,但不处理函数。 perlperf 说 Perl 会优化掉各种东西,但除了 ()-prototyped 函数,我不清楚是什么。

在 JavaScript 中,我会说 void obj.accessor();,然后我会确定它会运行但结果会被丢弃。但是,我不能使用undef $obj-&gt;accessor; 来获得类似的效果;编译通过Can't modify non-lvalue subroutine call of &amp;Klass::accessor 合法地失败。

【问题讨论】:

  • 嗯? perlperf 是关于改进用户代码的提示和技巧。它与 perl 编译器所做的任何内部优化无关。
  • 关于“结果将被丢弃”,在 Perl 中这只是无效的上下文,任何函数都可以以这种方式调用。您的示例不一定应用 void 上下文,因为它将在 dies_ok 调用周围函数的任何上下文中调用(评估的最后一条语句是函数的隐式返回值),但您可以在之后放置一个虚拟返回值,因此该语句是始终处于无效上下文中:$obj-&gt;accessor; 1;

标签: unit-testing perl optimization language-specifications code-elimination


【解决方案1】:

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

undef $obj-&gt;accessor 的意思类似于$obj-&gt;accessor = undef

【讨论】:

  • 如果你的答案比“AFAIK”更有力的参考/理由会很好。
  • 数百万行 Perl 代码的函数调用不使用返回值。我很赞同 Ujin734 的观点,即 Perl 永远不会优化它们。
  • 如果任何可能产生副作用的东西被优化掉,那将是一个错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-26
  • 1970-01-01
相关资源
最近更新 更多