未定义值作为散列引用的缺失错误

Posted

技术标签:

【中文标题】未定义值作为散列引用的缺失错误【英文标题】:Missing error for undefined value as hash reference 【发布时间】:2015-01-08 13:38:01 【问题描述】:

我有这两个 sn-ps 的代码,看起来应该产生相同的结果,但后者会导致错误。

1:

my $href = undef;
my @values = values % $href ;
# OK - @values is empty

2:

my $href = undef;
my %hash = % $href ; # <-- Error here
my @values = values %hash;
# ERROR: Can't use an undefined value as a HASH reference

为什么在同一行中有values 可以让它工作?我宁愿他们都抛出一个错误,因为使用未定义的值作为哈希引用显然是一个错误。我没有任何更新的 perl 版本可供测试,但这在 5.8.8 和 5.10.1 中可以重现。

【问题讨论】:

我认为this similar SO question 关于数组引用也适用于此。 ikegami 说“在左值上下文中取消引用自动激活(意思是当需要一个可修改的值时)。” perldoc -f values 说“请注意,这些值不会被复制,这意味着修改它们会修改散列的内容。” perlarchive.com/___TLC/7026.shtml ***.com/questions/1643717/… 如果这与自动生存相关,我预计no autovivification 会在第一个 sn-p 中导致错误。它没有。 @AKHolland 那是因为autovivification 只是将其保留为undef。使用 warnstrict 选项,例如no autovivification qw(fetch delete exists strict); $h = undef; values %$h;Reference vivification forbidden。见 brian d foy 的文章Turn off autovivification when you don’t want it 【参考方案1】:

自动激活是在引用undef时自动创建一个变量

my $ref;
say $ref // "[undef]";   # /  # Outputs: [undef]
$ref->abc = 123;            # This autovivifies a hash and a reference to it.
say $ref // "[undef]";        # Outputs: HASH(0x...)
say for keys %$ref;           # Outputs: abc

仅当解引用在左值上下文中时才会发生自动激活。

my $ref;
%$ref = ( abc => 123 );   # Autovivifies
my $ref;
my %h = %$ref;            # Error

对 subs 的参数在左值上下文中进行评估。我不知道命名运算符(如values)的操作数是否在左值上下文中评估是否有任何一致性,但显然values的操作数就是这种情况。

my $ref;
say $ref // "[undef]";   # /  # Outputs: [undef]
values %$ref;
say $ref // "[undef]";        # Outputs: HASH(0x...)

当自动验证不发生时,您将尝试遵循 undef,这没有任何意义,因此会导致错误。

【讨论】:

【参考方案2】:

Values 是一个函数,它接受散列、数组或泛型表达式作为参数(如 here 所述)。 如果您将 undef 作为参数传递给“values”,它只会将其检测为空并且不返回任何值。 另一方面,如果您尝试将 undef 显式转换为哈希,则会失败,因为它缺少键值对。

编辑:准确地说。 “严格”指令会发生此错误(无论如何,您应该始终使用它)。

【讨论】:

请在投票前仔细阅读。正如我所说,“价值观”是一个功能。调用它时你没有转换,因为 values 也接受一个表达式。 这是一个糟糕的例子,但你的解释是错误的。 values 不会以某种方式神奇地检测到 hashref 是 undef 并忽略它;散列被自动激活为空散列,values 对此进行操作。您可以通过以下方式看到这一点:perl -Mstrict -MData::Dump -e 'sub print_args dd \@_ my $href; print_args undef; print_args % $href ' 打印 [undef] 后跟 [] 此外,关闭自动生存会导致异常:perl -e 'no autovivification qw(fetch strict); my $foo; values % $foo ' 给出Reference vivification forbidden at -e line 1. 好的,我明白了。但是我仍然无法理解错误的原因是什么,为什么对函数参数进行简单的“如果已定义”检查应该是神奇的?我的意思是,好吧,我的解释可能是错误的,但正确的解释是什么? 查看我的 cmets 问题。这与this question 中的概念相同,除了使用哈希引用而不是数组引用。 values 创建一个左值上下文,因为修改结果会修改哈希。在左值上下文中取消引用自动激活,所以你得到一个空哈希:perl -Mstrict=refs -E 'values %$x; say $x' 打印HASH(0x1c3bd48)

以上是关于未定义值作为散列引用的缺失错误的主要内容,如果未能解决你的问题,请参考以下文章

为啥在运行玩笑测试时出现“未定义:x:y:属性”缺失错误?

C++ 类和继承错误:未定义对派生类的引用

C++17 编译器不应该发现对未定义值的传递引用吗?

我填写了表单上的所有值,我的 PHP 仍然返回未定义索引

Cloud Firestore 文档添加给出错误“参数“数据”的值不是有效的 Firestore 文档。不能使用“未定义”作为 Firestore 值”

编译错误 未定义的引用 怎么回事