2

这似乎是一件奇怪的事情,但是我如何在“内部”散列本身时引用散列呢?这是我正在尝试做的事情:

我有一个哈希哈希,最后有一个 sub,比如:

my $h = { A => [...], B => [...], ..., EXPAND => sub { ... } };

. 我正在寻找实现EXPAND以查看C此哈希中是否存在键,如果存在,则插入另一个键值对D

所以我的问题是,如何在不使用散列的变量名的情况下将对此散列的引用传递给 sub?我希望需要对一些散列执行此操作,并且我不想继续更改 sub 以引用它当前所在的散列的名称。

4

3 回答 3

5

您所拥有的是一些嵌套数组引用,而不是哈希。假设您实际上的意思是您有这样的东西:

my $h = { A => {...}, B => {...}, ..., EXPAND() };

在这种情况下,您不能$h从它自己的定义中引用,因为$h在表达式被完全评估之前不存在。

如果您满足于将其设置为两行,那么您可以这样做:

my $h = { A=> {...}, B => {...} };
$h = { %$h, EXPAND( $h ) };
于 2013-06-24T18:23:03.713 回答
4

The general solution is to write a function that, given a hash and a function to expand that hash, returns that hash with the expansion function added to it. We can close over the hash in the expansion function so that the hash's name doesn't need to be mentioned in it. That looks like this:

use strict;
use warnings;
use 5.010;

sub add_expander {
    my ($expanding_hash, $expander_sub) = @_;

    my $result = { %$expanding_hash };
    $result->{EXPAND} = sub { $expander_sub->($result) };

    return $result;
}

my $h = add_expander(
    {
        A => 5,
        B => 6,
    },
    sub {
        my ($hash) = @_;

        my ($maxkey) = sort { $b cmp $a } grep { $_ ne 'EXPAND' } keys %$hash;
        my $newkey = chr(ord($maxkey) + 1);
        $hash->{$newkey} = 'BOO!';
    }
);

use Data::Dumper;
say Dumper $h;
$h->{EXPAND}->();
say Dumper $h;

Notice that we are creating $h but that the add_expander call contains no mention of $h. Instead, the sub passed into the call expects the hash it is meant to expand as its first argument. Running add_expander on the hash on the sub creates a closure that will remember which hash the expander is associated with and incorporates it into the hash.

This solution assumes that what should happen when a hash is expanded can vary by subject hash, so add_expander takes an arbitrary sub. If you don't need that degree of freedom, you can incorporate the expansion sub into add_expander.

于 2013-06-24T18:37:46.213 回答
0

正在构建的哈希(可能)发生在EXPAND()运行之后。我可能会使用这样的东西:

$h = EXPAND( { A=>... } )

WhereEXPAND(...)返回修改后的 hashref 或如果原始需要保持不变则克隆。

于 2013-06-24T18:23:15.133 回答