简体   繁体   English

perl如何引用哈希本身

[英]perl how to reference hash itself

This might seem to be an odd thing to do, but how do I reference a hash while 'inside' the hash itself? 这似乎是一件奇怪的事情,但是当我在哈希自身内部时如何引用哈希呢? Here's what I'm trying to do: 这是我想做的事情:

I have a hash of hashes with a sub at the end, like: 我在哈希表的末尾有一个子哈希,例如:

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

. I'm looking to implement EXPAND to see if the key C is present in this hash, and if so, insert another key value pair D . 我正在寻找实现EXPAND以查看此哈希中是否存在键C ,如果存在,则插入另一个键值对D

So my question is, how do I pass the reference to this hash to the sub, without using the variable name of the hash? 所以我的问题是,如何在不使用哈希的变量名的情况下将对哈希的引用传递给子对象? I expect to need to do this to a few hashes and I don't want to keep having to change the sub to reference the name of the hash it's currently in. 我希望需要对一些哈希值执行此操作,并且我不想继续更改子项以引用其当前所在哈希的名称。

What you've got there is some nested array references, not hashes. 您所拥有的是一些嵌套数组引用,而不是哈希。 Let's assume you actually meant that you have something like this: 假设您实际上是说您有类似以下内容:

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

In that case, you can't reference $h from within its own definition, because $h does not exist until the expression is completely evaluated. 在那种情况下,您不能从其自己的定义中引用$h ,因为$h在表达式完全求值之前不存在。

If you're content to make it two lines, then you can do this: 如果您愿意将其设置为两行,则可以执行以下操作:

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

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 . 注意,我们正在创建$h但是add_expander调用中没有提到$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. 在子项的哈希上运行add_expander会创建一个闭包,该闭包将记住扩展程序与哪个哈希关联并将其合并到哈希中。

This solution assumes that what should happen when a hash is expanded can vary by subject hash, so add_expander takes an arbitrary sub. 该解决方案假定散列扩展时发生的情况可能因主题散列而异,因此add_expander采用任意子集。 If you don't need that degree of freedom, you can incorporate the expansion sub into add_expander . 如果不需要那种自由度,可以将扩展子合并到add_expander

The hash being built (potentially) happens after EXPAND() runs. (可能)正在建立的哈希发生在EXPAND()运行之后。 I would probably use something like this: 我可能会使用这样的东西:

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

Where EXPAND(...) returns the modified hashref or a clone if the original needs to remain intact. 如果原始文件需要保持原样,则EXPAND(...)返回修改后的hashref或副本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM