【问题标题】:Unexpected autovivification of arguments参数的意外自动激活
【发布时间】:2023-03-28 14:25:02
【问题描述】:

显然我对 no autovivification 杂注的理解并不完美,因为以下脚本的 not-dying-on-line-19 行为让我非常惊讶。

use 5.014;
use strict;
use warnings;
no autovivification qw(fetch exists delete warn);

{
  my $foo = undef;
  my $thing = $foo->{bar};

  # this does not die, as expected
  die if defined $foo;
}

{
  my $foo = undef;
  do_nothing( $foo->{bar} );

  # I would expect this to die, but it doesn't
  die unless defined $foo;
}

sub do_nothing {
  return undef;
}

运行脚本会产生:

Reference was vivified at test.pl line 8.

问题:即使no autovivification 有效,为什么$foo->{bar} 作为参数提供给sub 时$foo 会自动激活?

【问题讨论】:

  • 你安装了吗?也许将 warn 添加到 unimports 列表中。那将是no autovivification qw<fetch exists delete warn>;,看看是否有警告,当它像文档说的那样被避免时。
  • 它已安装,否则脚本将在第 11 行终止。我已使用添加 warn 的结果更新了问题。
  • 这并不奇怪。 Perl 并不知道do_nothing 什么都不做,因为你给了它一个参数,它必须自动激活它,这样你就可以在 sub 中使用它。特别是,它不知道你对$_[0]是否在do_nothing做作。
  • 这是有道理的。不过,这感觉像是可以在文档中更清楚地说明的东西,因为任何来自按值传递语言的人都会感到惊讶。
  • 它在 sub 中的运行方式有一个关键的区别(它是一个 lvalue 上下文,对象必须是可修改的)。我认为this answer 可以解释它。

标签: perl autovivification


【解决方案1】:

在子例程调用中,函数的参数别名为@_,因此必须可以修改它们。这提供了一个 lvalue 上下文,它将触发自动激活。

当我们查看您在 autovivification 中使用的功能的描述时,它们包括:

  • 'fetch' -- "右值解引用表达式"
  • 'exists' -- "取消引用作为 exists 一部分的表达式"
  • 'delete' -- "取消引用作为 delete 一部分的表达式"

这些都不处理左值(warn 也不处理)。

要在子例程调用中停止自动激活,您需要添加store

关闭左值解引用表达式的自动激活,例如: [...]

文档继续示例,包括子例程调用。

当我将它添加到您的代码中时,

no autovivification qw(fetch exists delete warn store);
# ...

我明白了

参考在 noautoviv.pl 第 8 行被激活。 参考在 noautoviv.pl 第 16 行被激活。 死于 noautoviv.pl 第 19 行。

【讨论】:

    猜你喜欢
    • 2019-04-02
    • 1970-01-01
    • 2020-11-24
    • 2011-05-17
    • 2015-08-26
    • 1970-01-01
    • 1970-01-01
    • 2015-03-11
    • 2019-01-31
    相关资源
    最近更新 更多