2017-12-08 6 views
1

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(); 
     } 
    ) 
); 

配列をハッシュに正しく変換する方法がわかりません。私は、無名関数が参照として渡されるため、動作すると思っていました。しかし、それはまだ配列のように@_上に索引付けされ、キーは@_の索引になります。

答えて

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.pmをヘルパーを入れた場合は、その後、ちょうど

use Helper (
    \%SOME_CONFIG, 
    .... 

しかし、use句は、%SOME_CONFIGはまだしていないときには、コンパイル時に処理されていることができますそれがBEGINブロックに定義する必要があります。あなたはまだ使用句でそれにアクセスできるように、しかし、ブロックの外にそれを宣言する必要があります:

池上が示唆されているように簡素化された
my %SOME_CONFIG; 
BEGIN { 
    %SOME_CONFIG = (field => 'and its value'); 
} 

を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"; 
     }, 
    ], 
); 
+0

'{first_helpers => ...、}、{second_helpers => ...}' 'でなければならない{first_helpers => ...、second_helpers => ...} '(適切に' import'を変更して) – ikegami

2

小文字のモジュール名はPerlによって予約されており、慣習としてプラグマに使用されています。これは2つのミスですので、モジュールの名前をHelperに変更しましょう。 (一致するファイル名を変更することを忘れないでください!)引数は


  • "Helper"
  • \%SOME_CONFIG
  • "first_helper"
  • sub { 1 }
  • sub { 2 }
  • "second_helper"
  • sub { 3 }

おそらく、配列内のサブレフリーに合格することを意図していますが、括弧を使用していました。父親は優先順位を変えるだけです。代わりに、次を使用している必要があります。

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; 
    } 
} 
関連する問題