将内部数组传递给函数

时间:2017-11-15 12:03:34

标签: perl hashtable

我正在尝试将内部数组传递给Perl中的函数。 这是我的Perl程序。

#!/usr/bin/perl
use strict;
use warnings;

my %data = (
    'a' => (
        x => 'Hello',
        y => 'World'
    ),
    'b' => (
        x => 'Foo',
        y => 'Bar'
    )
);

#prototype
sub p(\%);

{ #main
    p(%data{'a'}); # should print "Hello Wolrd".
}

sub p(\%) {
    print "$_[0]{x} $_[0]{y}\n";
}

相反,我收到以下错误:Type of arg 1 to main::p must be hash (not key/value hash slice)

这有效:

#!/usr/bin/perl
use strict;
use warnings;

#prototype
sub p(\%);

{ #main
    my %a = (
        x => 'Hello',
        y => 'World'
    );
    p(%a);
}

sub p(\%) {
    print "$_[0]{x} $_[0]{y}\n";
}

因此方法调用一定有问题。但是什么? a 的内容是一个哈希值,因此p(之后的第一个字符必须是%(我也试过了p($data{'a'});,但它又留下了另一个错误(这似乎是合乎逻辑的,因为 a 的内容不是标量。)我不必手动创建对散列和取消引用的引用,因为我声明了函数原型。我错过了什么? / p>

2 个答案:

答案 0 :(得分:4)

您对结构的定义是错误的。内部哈希需要使用{},而不是()

my %data = (
    a => {
        x => 'Hello',
        y => 'World'
    },
    b => {
        x => 'Foo',
        y => 'Bar'
    }
);

另外,要获取单个哈希元素,请使用$data{'a'}(或甚至$data{a}),而不是%data{'a'}

此外,请参阅Why are Perl 5's function prototypes bad?了解为何不使用原型。在纠正上述语法之后,即使没有原型,代码也能正常工作。如果您确实需要原型,请使用%,而不是\%。但你显然不知道原型的确切用途,所以不要使用它们。

答案 1 :(得分:3)

您的代码中没有数组。并且代码中没有方法调用。

您的哈希定义不正确。你不能在其他哈希中嵌入哈希。您需要使用哈希引用。像这样:

my %data = (
    'a' => {
        x => 'Hello',
        y => 'World'
    },
    'b' => {
        x => 'Foo',
        y => 'Bar'
    }
);

注意,我使用{ ... }来定义您的内部哈希值,而不是( ... )

但这仍然给我们一个错误。

  

arg 1到main :: p的类型必须是在passhash第20行的哈希(不是哈希元素),靠近"})"

如果不清楚,我们可以尝试添加use diagnostics以获取错误的更多详细信息:

  

(F)此函数要求该位置的参数为某种类型。数组必须是@NAME或@ {EXPR}。哈希必须是%NAME或%{EXPR}。不允许隐式解除引用 - 使用{EXPR}表单作为显式解除引用。见perlref。

参数类型定义来自原型。您的原型是\%。人们通常认为这意味着哈希引用。它没有。这意味着,"在这个位置给我一个真正的哈希,我将引用它并将该引用传递给子程序"。

(看,这就是人们说原型不应该用于Perl的原因 - 他们通常不会做你认为他们做的事情。)

您没有传递哈希值。您正在传递哈希引用。您可以通过在子例程调用中取消引用哈希来修复它。

p(%{$data{a}});

但那是一个非常愚蠢的想法。获取哈希引用并将其转换为哈希,以便Perl可以将其引用传递给子例程。

您真正想要做的是将原型更改为$,以便子例程接受哈希引用。然后,您可以使用ref检查是否有哈希引用。

但这仍然有点过分。人们建议不要使用Perl原型,这是有充分理由的。只需删除它。