将内部数组传递给函数

Passing an inner array to a function

我正在尝试将内部数组传递给 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 的内容不是标量)。我不必手动创建对散列的引用和取消引用,因为我声明了函数原型。我错过了什么?

你的结构定义有误。内部哈希需要使用 {},而不是 ().

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? 为什么不使用原型。如上所述更正语法后,即使没有原型,代码也能正常工作。如果您确实需要原型,请使用 %,而不是 \%。但是你显然不知道原型的确切用途,所以不要使用它们。

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

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

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

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

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

Type of arg 1 to main::p must be hash (not hash element) at passhash line 20, near "})"

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

(F) This function requires the argument in that position to be of a certain type. Arrays must be @NAME or @{EXPR}. Hashes must be %NAME or %{EXPR}. No implicit dereferencing is allowed--use the {EXPR} forms as an explicit dereference. See perlref.

参数类型定义来自原型。你的原型是\%。人们通常认为这意味着哈希引用。它没有。这意味着,"give me a real hash in this position and I'll take a reference to it and pass that reference to the subroutine".

(看,这就是为什么人们说原型不应该在 Perl 中使用——他们通常不会按照您认为的那样去做。)

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

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

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

您真正想要做的是将原型更改为 $,以便子例程接受散列引用。然后,您可以使用 ref.

检查您是否有哈希引用

但这仍然是矫枉过正。人们出于非常充分的理由建议不要使用 Perl 原型。只需删除它。