我似乎无法弄清楚如何正确地将hashref传递给模块。
#module helper.pm
my %helpers;
sub import {
shift @_; #returns "helper"
%SOME_CONFIG = %{shift @_};
foreach my $hashref (%{@_}){
$helpers{$hashref->{key}} = $hashref->{value};
}
}
#main
use helper(
\%SOME_CONFIG,
"first_helper" => (
sub {
return do_something();
},
sub {
return do_something_else();
}
),
"second_helper" => (
sub {
return something_else();
}
)
);
我不确定如何正确地将数组转换为哈希。我认为它有效,因为匿名函数作为引用传递。但是它仍然对@_进行索引,就好像它是一个数组,并且键成为@_的索引。
答案 0 :(得分:2)
Perl保留小写模块名称,惯例是将它们用于pragma。这是两次未命中,因此我们将模块重命名为Helper
。 (别忘了更改文件名以匹配!)
参数是
"Helper"
\%SOME_CONFIG
"first_helper"
sub { 1 }
sub { 2 }
"second_helper"
sub { 3 }
你可能想要在数组中传递子引用,但是你使用了parens。 Parens只是改变了优先权。相反,您应该使用以下内容:
use Helper (
\%SOME_CONFIG,
"first_helper" => [
sub {
return do_something();
},
sub {
return do_something_else();
}
],
"second_helper" => [
sub {
return something_else();
}
],
);
现在,参数是
"Helper"
\%SOME_CONFIG
"first_helper"
[ sub { 1 }, sub { 2 } ]
"second_helper"
[ sub { 3 } ]
除了\%SOME_CONFIG
之外,其他地方没有哈希值,但你有一个哈希解除引用。那不好。我们可以在调用者中构建一个哈希值,但由于我们可以按原样处理数据,因此不需要再这样做了。解决方案:
sub import {
my $class = shift;
my $config = shift;
my %new_helpers = @_;
for my $id (keys(%new_helpers)) {
$helpers{$id} = $new_helpers{$id};
}
}
或
sub import {
my $class = shift;
my $config = shift;
%helpers = ( %helpers, @_ );
}
或
sub import {
my $class = shift;
my $config = shift;
while (@_) {
my $id = shift;
$helpers{$id} = shift;
}
}
答案 1 :(得分:1)
如果您的模块不是编译指示,即它不会更改代码的解析方式,请使用大写名称。
哈希的值是标量,因此如果要为键分配多个子例程,则必须使用数组引用。
#! /usr/bin/perl
use warnings;
use strict;
{
package Helper;
my %helpers;
sub import {
my $class = shift;
my %SOME_CONFIG = %{ shift; };
for my $hashref (@_){
@helpers{keys %$hashref} = values %$hashref;
}
use Data::Dumper;
$Data::Dumper::Deparse = 1; # To show the code, as well.
warn Dumper \%SOME_CONFIG, \%helpers;
}
}
my %SOME_CONFIG = ( field => 'and its value' );
sub do_something {
warn "Doing something";
}
sub do_something_else {
warn "Doing something else";
}
Helper->import(
\%SOME_CONFIG,
{ first_helpers => [
\&do_something,
\&do_something_else,
] },
{ second_helpers => [
sub {
warn "Inside the 2nd helper";
},
] },
);
如果你将Helper放入自己的Helper.pm文件中,那么你可以
use Helper (
\%SOME_CONFIG,
....
但是,use
子句在编译时处理,当%SOME_CONFIG仍然没有被填充时,所以你需要在BEGIN块中定义它。但是,您仍然需要在块之外声明它,以便在use子句中访问它:
my %SOME_CONFIG;
BEGIN {
%SOME_CONFIG = ( field => 'and its value' );
}
简化为ikegami建议:
在Helper.pm中,只需执行
%helpers = @_;
而不是for my $hashref
。在主程序中,使用
use Helper(
\%SOME_CONFIG,
first_helpers => [
\&do_something,
\&do_something_else,
],
second_helpers => [
sub {
warn "Inside the 2nd helper";
},
],
);