1

我有一个递归函数,它使用ref递归地遍历数据结构。如果 ref 返回一个空字符串,则调用回调。我的问题是我需要在我的数据结构中存储一个 hash-ref,它会被我的函数视为标量。

本质上,我需要做这样的事情;

    my %hash = fillHash();
    $hash{'abc'}{'def'} = \%hash;

我想知道是否有某种方法可以存储 \%hash 以使其被视为标量而不是引用。可能喜欢/

     $hash{'abc'}{'def'} = scalar \%hash;

我只是在寻找一种将链接添加到我的数据结构的父节点的方法,但仍然能够递归地遍历它。

谢谢

4

3 回答 3

3

您可以使用我所做的来区分值和结构,我称它们为“间接数组”(在我的例子中)。

在您的情况下,它看起来像这样:

 $hash{'abc'}{'def'} = scalar \\%hash;

ref( $hash{'abc'}{'def'} )'REF',以防你想知道。然后你可以决定你需要取消引用它两次:

$hash_ref = ${ $hash{'abc'}{'def'} };
于 2012-08-15T17:15:23.527 回答
2

我认为@MarkCanlas 在他的建议中给出了正确的解决方案,可以考虑采用不同的方式来构建数据。除此之外,您可以进行双重参考。

my $scalar_ref = \%hash;
$other_hash{abc}{def} = \$scalar_ref;

现在,当你检查那个ref时,你会回来"REF"并且可以做一些不同的事情。

于 2012-08-15T17:15:16.940 回答
1

首先,您应该意识到所有引用在定义上都是标量。

您想要的是可以在任何地方都可以作为参考的东西,但在您的步行功能中。任何一种魔法参考都无法真正实现这一点。步行功能是必须添加逻辑的地方。你可以让它跟踪它已经看到的东西:

my %h = (
    foo => "bar",
    inner => {
        foo => 42
    }
);

$h{inner}{parent} = \%h;

sub walk
{
    my ($h, $cb, $path, $seen) = @_;
    $path //= "";
    $seen //= {};
    $seen->{$h}=1;
    while(my ($k, $v) = each %$h) {
        if(ref($v)) {
            walk($v, $cb, "$path/$k", $seen) if !$seen->{$v};
        } else {
            $cb->($k, $v, "$path/$k");
        }
    }
}

walk(\%h, sub {
  my ($key, $value, $path) = @_;
  print "walker found $key ($path) => $value\n";
});

或者你可以让它识别某些parent特殊的键,然后跳过它们。

于 2012-08-15T17:16:51.763 回答