如何取消引用从类方法返回的哈希?

sgs*_*sax 7 perl hash class dereference

我有一个类,返回一个哈希的方法.通常,我会得到如下结果:

%resp = $myclass->sub($foo);
Run Code Online (Sandbox Code Playgroud)

然后像这样访问返回的哈希的成员:

$resp{key}{subkey};
Run Code Online (Sandbox Code Playgroud)

在2d哈希的情况下.

我认为必须有一种方法将它组合成一条优雅的线,如下所示:

$myclass->sub($foo)->{key}{subkey}
Run Code Online (Sandbox Code Playgroud)

这显然没有被正确解除引用,因为Perl在尝试运行代码时返回此信息:

Can't use string ("1/8") as a HASH ref

在尝试随机解引用序列时,通过在Perlmonks上查看"References quick reference",我提出了以下内容,Perl没有抱怨,但也没有返回我正在寻找的内容:

$%{$myclass->sub($foo)}->{key}{subkey}
Run Code Online (Sandbox Code Playgroud)

有人能告诉我神奇的解引用转义序列是做什么的吗?

Sin*_*nür 9

你要做的不是优雅也不可取.你以某种方式设法在标量上下文中调用例程(这是"1/8"对应的).

返回哈希引用.

现在,来看看:

#!/usr/bin/perl

package My::Mine;

use strict; use warnings;

sub test {
    my %h = (
        a => { z => 1},
        b => { y => 2},
    );
    return %h;
}

package main;

use strict; use warnings;

my $class = 'My::Mine';

print { $class->test }->{a}{z}, "\n";
Run Code Online (Sandbox Code Playgroud)

那样不行.相反,你必须这样做:

print +{ $class->test }->{a}{z}, "\n";
Run Code Online (Sandbox Code Playgroud)

现在,这很优雅(不!)见perldoc -f print.

长话短说,返回哈希的引用.

请注意,您正在构建的新匿名哈希不是免费的.从子例程返回哈希作为平面列表的成本也不是.

  • +1代表清楚地解释1/8.另外,返回一个哈希的另一个缺点 - 如果你认为"这是一个副本,所以我可以安全地修改它",它会让你陷入虚假的安全感 - 但是,数据结构的内部结构仍然是不是深度克隆,因此您无法安全地修改它们. (3认同)
  • +是对解析器的提示,即打印后的{...}构造不是打印方法的间接对象.这用于像'print {sub_returns_a_file_handle()}"东西打印的情况 - 注意在打开引号之前没有逗号";` (2认同)

Eri*_*rom 6

更改sub以返回哈希引用最有效,但要获得您正在寻找的功能:

{ $myclass->sub($foo) }->{key}{subkey}
Run Code Online (Sandbox Code Playgroud)

这将从返回的列表中创建一个哈希引用sub,然后立即取消引用它

编辑:从您的sub而不是哈希(作为列表)返回hashref的优势主要是性能.在hashref的情况下,哈希被创建一次,然后被访问.在列表的情况下,创建哈希,然后转换为列表,然后再次创建,然后解除引用.对于小哈希,这不会花费太多时间,但对于较大的哈希,它只是运行时不必要的工作.基本上,如果您计划在某些地方将数据用作列表,并在其他地方使用哈希,则将哈希作为列表返回是可以的.但是如果你总是计划将它用作哈希值,那么返回引用会更清晰,更快.


DVK*_*DVK 1

只需返回一个 hashref 而不是哈希:

$myclass->sub($foo)->{key}->{subkey}