我正在尝试将内部数组传递给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>
答案 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原型,这是有充分理由的。只需删除它。