2017-11-15 9 views
0

内部配列を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"; 
} 

だから、メソッド呼び出しに何か問題がなければなりません。しかし何? の内容はハッシュなので、p(後の最初の文字が%が(私もp($data{'a'});を試してみましたでなければならないが、それはの内容から、論理的と思われる別のエラー(と私の葉)スカラーではありません。私は、関数のプロトタイプを宣言しているため、手動でハッシュと間接参照への参照を作成する必要はありません。私は何をしないのですか?

答えて

3

コードに配列がありません。あなたのコードにはメソッド呼び出しがありません。

ハッシュが正しく定義されていません。他のハッシュの中にハッシュを埋め込むことはできません。ハッシュリファレンスを使用する必要があります。このように:

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.

パラメータタイプの定義は、プロトタイプから来ます。あなたのプロトタイプは\%です。人々はしばしばそれがハッシュリファレンスを意味すると考えます。それはしません。それは、「私にこのポジションで実際のハッシュを与えて、それを参照して、その参照をサブルーチンに渡す」という意味です。

(人々はプロトタイプがPerlで使用すべきではないと言う理由です、参照してください - 彼らは多くの場合、あなたは彼らが何を考えて行わない。)

をあなたはハッシュを渡していません。ハッシュリファレンスを渡しています。サブルーチンコールでハッシュを逆参照することで修正できます。

しかし、それは本当にばかげた考えです。ハッシュリファレンスを取得してハッシュに変換すると、Perlはそのリファレンスをサブルーチンに渡すことができます。

本当にしたいのは、プロトタイプを$に変更して、サブルーチンがハッシュリファレンスを受け入れるようにすることです。 refを使用してハッシュリファレンスがあることを確認できます。

しかし、それでもやりすぎです。 Perlのプロトタイプを使用することには非常に良い理由があります。ただそれを削除します。

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?を参照してください。上記の構文を修正した後、プロトタイプを使わなくてもコードは動作します。プロトタイプが本当に必要な場合は、で、\%ではなく、%を使用してください。しかし、プロトタイプがどのような目的のために使用されているのか正確には分かりませんので、使用しないでください。

+0

内側の配列定義に中カッコを使用しても何も変更されませんが、エラーは残ります。 '$ data {'a'}'を使って要素にアクセスすると、他のエラーメッセージが表示されます。これは 'arg :: 1のタイプ:: main :: pはハッシュ(ハッシュ要素ではありません)'でなければなりません。プロトタイプ宣言を削除すると実際にはうまくいきますが、 'main :: p()はex2.pl 17行目でプロトタイプをチェックするのが早すぎます。' '警告を使用しないようにします。それらの多くは私にはヘルフプルに見えます。プロトタイプ**や**を削除せずにこれを修正することも可能ですか? – Paramaeleon

+1

プロトタイプの両方の言及を削除します。 – choroba