@$ref->{@keys} 试图访问什么?

发布于 2024-12-16 02:00:28 字数 2234 浏览 0 评论 0原文

有关哈希切片的问题的答案,有人想知道如何使用箭头语法通过哈希引用访问哈希切片,认为也许

@$ref->{@keys}

可以这样做。

是的,正确的语法是 @$ref{@keys}@{$ref}{@keys},但这不是这个问题的重点。

我试图计算出带有箭头的表达式所需的数据结构:

#! /usr/bin/env perl

use strict;
use warnings;

my $ref = {"a" => 1, "b" => 2, "c" => 3};

my @keys = qw/ a b c /;

#$ref = [ { a => 9, b => 8, c => 7 } ];
#$ref = [ { a => {}, b => {}, c => {} } ];
print @$ref->{@keys}, "\n";

正如所写,代码失败了

Not an ARRAY reference at ./prog line 12.

这是有道理的: @$ref 想要对数组的引用,所以我尝试包装哈希引用内部对匿名数组的引用。这些尝试失败了,

Can't use an undefined value as a HASH reference at ./prog line 12.

跟踪输出是

$ debugperl -Dt prog
[...]
(prog:12)   pushmark
(prog:12)   padsv($ref)
(prog:12)   rv2av
(prog:12)   rv2hv
Can't use an undefined value as a HASH reference at prog line 12.

print 行的语法转储是

$ debugperl -Dx prog
[...]
    {
484     TYPE = print  ===> 2
        FLAGS = (VOID,KIDS)
        {
485         TYPE = pushmark  ===> 486
            FLAGS = (SCALAR)
        }
        {
372         TYPE = helem  ===> 371
            FLAGS = (SCALAR,KIDS)
            {
487             TYPE = rv2hv  ===> 361
                TARG = 5
                FLAGS = (SCALAR,KIDS,REF)
                PRIVATE = (STRICT_REFS)
                {
373                 TYPE = rv2av  ===> 487
                    TARG = 4
                    FLAGS = (SCALAR,KIDS,REF)
                    PRIVATE = (STRICT_REFS)
                    {
486                     TYPE = padsv  ===> 373
                        TARG = 1
                        FLAGS = (SCALAR,MOD)
                    }
                }
            }
            {
361             TYPE = padav  ===> 372
                TARG = 2
                FLAGS = (SCALAR)
            }
        }
        {
371         TYPE = const  ===> 484
            TARG = 19
            FLAGS = (SCALAR)
        }
    }
[...]

未定义值来自哪里?对于 $ref 的什么值,程序会正常终止?

In a comment on an answer to a question about hash slices, someone wanted to know how to use arrow syntax to access a hash slice through a hash reference, thinking perhaps that

@$ref->{@keys}

would do so.

Yes, the correct syntax is either @$ref{@keys} or @{$ref}{@keys}, but that's beside the point of this question.

I tried to work out the data structure that the expression with an arrow requires:

#! /usr/bin/env perl

use strict;
use warnings;

my $ref = {"a" => 1, "b" => 2, "c" => 3};

my @keys = qw/ a b c /;

#$ref = [ { a => 9, b => 8, c => 7 } ];
#$ref = [ { a => {}, b => {}, c => {} } ];
print @$ref->{@keys}, "\n";

As written, the code fails with

Not an ARRAY reference at ./prog line 12.

That makes sense: @$ref wants a reference to an array, so I tried wrapping hash references inside a reference to an anonymous array. Those attempts failed with

Can't use an undefined value as a HASH reference at ./prog line 12.

The trace output is

$ debugperl -Dt prog
[...]
(prog:12)   pushmark
(prog:12)   padsv($ref)
(prog:12)   rv2av
(prog:12)   rv2hv
Can't use an undefined value as a HASH reference at prog line 12.

The syntax dump for the print line is

$ debugperl -Dx prog
[...]
    {
484     TYPE = print  ===> 2
        FLAGS = (VOID,KIDS)
        {
485         TYPE = pushmark  ===> 486
            FLAGS = (SCALAR)
        }
        {
372         TYPE = helem  ===> 371
            FLAGS = (SCALAR,KIDS)
            {
487             TYPE = rv2hv  ===> 361
                TARG = 5
                FLAGS = (SCALAR,KIDS,REF)
                PRIVATE = (STRICT_REFS)
                {
373                 TYPE = rv2av  ===> 487
                    TARG = 4
                    FLAGS = (SCALAR,KIDS,REF)
                    PRIVATE = (STRICT_REFS)
                    {
486                     TYPE = padsv  ===> 373
                        TARG = 1
                        FLAGS = (SCALAR,MOD)
                    }
                }
            }
            {
361             TYPE = padav  ===> 372
                TARG = 2
                FLAGS = (SCALAR)
            }
        }
        {
371         TYPE = const  ===> 484
            TARG = 19
            FLAGS = (SCALAR)
        }
    }
[...]

Where is the undefined value coming from? For what values of $ref does the program terminate normally?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

慵挽 2024-12-23 02:00:28

它不是有效的(或者至少没有意义)Perl 语法——我有点惊讶它没有被标记为语法错误。

我首先认为它试图在标量上下文中评估数组 @$foo 并将结果用作哈希引用,但这似乎并不是正在发生的事情。
相反,从您发布的调试输出来看,它看起来更像是尝试直接使用内部数组变量(AV)结构作为哈希引用(RV),这是一种标量(SV;请参阅 perlguts 了解详细信息)。

我没有查看源代码,但看起来 rv2hv 例程要么注意到它被赋予了错误的结构类型并返回 null,要么只是尝试将 AV 用作 RV 并且这样就达到了同样的效果。 (抱歉,如果这听起来有点混乱,自从我上次查看 Perl 的内部结构以来已经有好几年了。)

您可能需要考虑提交错误报告。

顺便说一句,演示效果的更简单的测试用例就是 @foo->{bar}

It's not valid (or at least not meaningful) Perl syntax — I'm a bit surprised it's not flagged as a syntax error.

I first thought it was trying to evaluate the array @$foo in scalar context and use the result as a hash reference, but that doesn't quite seem to be what's going on.
Rather, from the debug output you posted, it looks more like it's trying to directly use the internal array variable (AV) structure as a hash reference (RV), which is a type of scalar (SV; see perlguts for details).

I haven't looked at the source, but it looks as if the rv2hv routine either notices that it's been given the wrong kind of structure and returns null, or just tries to use the AV as an RV and achieves the same effect that way. (Sorry if that may sound a bit muddled, it's been some years since I last looked at the internals of perl.)

You might want to consider submitting a bug report.

BTW, a simpler test case that demonstrates the effect is just @foo->{bar}.

三生一梦 2024-12-23 02:00:28
@$ref->{@keys}

意味着

scalar(@$ref)->{@keys}

so it 应该等同于

my $ref2 = @$ref;
$ref2->{@keys}

It's not,所以这是一个错误。它仍然存在于即将成为 Perl 5.16.0 的近当前状态中。 (具体为 v5.15.4)

请使用 perlbug 命令行工具进行报告。 (只需输入 perlbug 并回答几个简单的问题。)

@$ref->{@keys}

means

scalar(@$ref)->{@keys}

so it should be equivalent to

my $ref2 = @$ref;
$ref2->{@keys}

It's not, so it's a bug. It's still present in the near-current state of what will become Perl 5.16.0. (v5.15.4, to be specific)

Please report using the perlbug command line tool. (Just enter perlbug and answer a few simple questions.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文