将多个变量传递给模块

时间:2017-12-08 22:23:04

标签: perl

我似乎无法弄清楚如何正确地将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();
        }
    )
);

我不确定如何正确地将数组转换为哈希。我认为它有效,因为匿名函数作为引用传递。但是它仍然对@_进行索引,就好像它是一个数组,并且键成为@_的索引。

2 个答案:

答案 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";
        },
    ],
);