• 締切済み

Perlのサブルーチンの引数に配列やハッシュをCall by Valueすることはできない?

haporunの回答

  • haporun
  • ベストアンサー率40% (230/562)
回答No.4

byval(@a)と書くと($a[0..$#a])を渡したのと同じになります。 リファは入ってません。 しかし、@_は@aの参照ではありません。 $_[0]から$_[$#a]が$a[0]から$a[$#a]の参照なのです。 だから内部で@_=@otherとか代入しても、関係ないです。 また、それぞれが参照である期間は、サブルーチンスコープ内のみです。 これはVisual BasicやJAVAなど、参照で引数を取るタイプの言語としては標準の動きみたいです。 ちなみに自作サブルーチンに渡す引数は、全部リスト扱いです。 (@a, 5, 6, 'ほげ')とかリスト表現できるように、それをサブルーチンに渡してるだけです。 ちなみにbyval(%hash)したら、さすがにハッシュリファが渡ってしまいました。 また、ハッシュ自体をreturnできそうもないので、これもまた考え物です。

stanaka
質問者

お礼

 まず,ありがとうございます(笑).  補足を書いてから気がついたので,ここに書かせていただきます.  ひょっとして,サブルーチンの引数に配列を指定すると,(引数はリストコンテキストなので)配列がリストに展開されて,配列の要素分の引数がサブルーチンに引き渡される,と言うことですか?.とすると, > $_[0]から$_[$#a]が$a[0]から$a[$#a]の > 参照なのです。  とはいいますが,$_[0]から$_[$#a]には$a[0]から$a[$#a]それぞれへのリファレンスではなく,コピー実体が入ってそうな気がするんですが・・・.  ちょっと今,実験できる環境ではないので,帰ってから実験してみます.

stanaka
質問者

補足

 がーん.  えーっと,俺様なんだか激しくマチガイ理解の予感が・・・.  ちょっ,ちょっとまってくださいね.  今,僕は, sub subroutine{  my $sch = $_[0];  my $arr = @{ $_[1] };  my $hsh = %{ $_[2] }; }  とやっておけば, &subroutine( $sch, \@arr, \%hsh );  とやったときに,ローカルスコープの変数へそれぞれちゃんとコピーできるのではないか,と理解しているのですが,これは間違っていますか?.  それと,ハッシュをreturn出来ない,と言うのは,サブルーチン内で  return %hsh;  と言うのが出来ない,と言うことですか?.  また,僕はいまいちリストコンテキストと言う物が理解できなかったのですが,ここを読んでるうちに一つ思ったことがあります.次のような物ですが,これはまた間違っているでしょうか?,またどこが間違っているでしょうか?.  つまり,データ構造としては「リスト」,「配列」,「ハッシュ」があり,それぞれ, ( e1, e2, e3 ); [ e1, e2, e3 ]; ( 'k1' => e1, 'k2' => e2, 'k3' => e3 );  のような記法で表現できる.ここで,@変数にリストの記法で代入を行うと,配列が生成され,%変数にリストの記法で代入を行うと,偶数番要素がキー,奇数番要素が要素となるハッシュが生成される.  同様にリストの記法の左辺に@変数を代入すると,右辺の配列の要素と同じ値を要素とするリストが生成され,代入される.  分けわかんなくなって来てますが,よろしくお願いします.

関連するQ&A

  • Perlのクラス(*.pm)からuseする側の*.cgi内ののスカラやハッシュ、配列の参照は可能でしょうか?

     Perlのクラス(*.pm)からuseする側の*.cgi内ののスカラやハッシュ、配列の参照は可能でしょうか? いろいろなサーバに対応させやすくするため 1行目(Perlのパス)や各種モジュールのパスや設定情報を*.cgiに書いてプログラム本体は*pmに置きたいのです。 それとももっといい方法がございますでしょうか。  教えて!ください。

    • ベストアンサー
    • Perl
  • リファレンスをサブルーチンの戻り値にしてもOKですか?

    ■ サブルーチン内部で処理した結果を格納した、配列、ハッシュ、スカラーなどのデータを戻り値として利用する必要があります。その場合、どうするのが標準的なやり方でしょうか? ■ return (配列へのリファレンス, ハッシュへのリファレンス, スカラー); などとやってしまっても問題はないでしょうか? ■ 下のプログラムを試したところ、予想に反しちゃんと 「31415」と表示されました。 #!/usr/bin/perl -w sub subroutine{ my @a = (3, 1, 4, 1, 5); return \@a; } my $b = subroutine{}; print @$b; ■ サブルーチン内部で使用した変数へのリファレンスをサブルーチン 外で使っていいのだろうか? サブルーチンの処理が終了した時点でサブルーチン内部で使用した 変数はメモリーから消去されるのかと思ったものですから。

    • ベストアンサー
    • Perl
  • サブルーチンの引数としてハッシュを渡したい

    ハッシュを引数として受け取り、そのハッシュの内容を csv形式に変換し出力するというサブルーチンを作っています。 ハッシュのキー名は固定なのですが、 引数として渡すハッシュの名前がバラバラの場合、 それを引数としてうけとることは可能なのでしょうか? また、どのように受け取ればいいでしょうか?

    • ベストアンサー
    • Perl
  • Perl・DBIでの汎用selectサブルーチンを作成するには?

    Perl・DBIで、select文発行のサブルーチンを作成していますが、未熟なため、完成できません。 呼び出し側では、下の記述のように、サブルーチンの引数として、SQL文を渡し(SELECT系)、戻り値として、SELECTされた結果を取得したい(配列もしくは、ハッシュで)と思っております。 もし、参考にできる、サイト・ サンプルサイト等のご紹介でも、結構ですので、ご教授くださればと思います。(処理の流れ等の箇条書きでもかまいません。) -------------------------------------------- # 呼び出し側(メインルーチン) $name;#テンプレート置換変数  $age; #テンプレート置換変数 my $sql =<<"EOQ"; # この抽出select文はその都度変わる。 select NAME,AGE from EMP EOQ my @row = &do_select($sql); $name = $row[0]; $age = $row[1]; もしくは、 $name = $hash_ref->{NAME}; $age = $hash_ref->{AGE}; のような記述で代入。 # テンプレートを読み込んで、置換処理で代入 ※幾分省略しています。 <table> for(){# SELECT分の結果の行数分繰り返し処理。 <tr>  <td>$name</td>  <td>$age</td> </tr> } </table> my $dbh = DBI->connect($dbhost, $dbuser, $dbpass) || die $dbh::errorstr; ##### select発行サブルーチン ####### sub do_select{ my $sth; my $rv; my @row; # 戻り値(フィールドが入る) my %dbhash; # 戻り値はこちらかな? my $sql = shift(@_); # select文 $sth = $dbh->prepare("$sql"); $rv = $sth->execute || die $sth->errstr; while($hash_ref = $sth->fetchrow_hashref){      # print "$hash_ref->{TITLE}<br>"; # ここに、何かの処理が入る } return @row; }

    • ベストアンサー
    • Perl
  • <Perl>参照配列の出力に失敗する。

    <Perl>参照配列の出力に失敗する。 お世話になります。 配列の出力部で以下のエラーが出力されます。 Use of uninitialized value in print at test2.pl line 12. -----コーディングは以下の通りです。----- #!C:\perl use strict; use warnings; my @l = (); #----------- #GetDataへCSVファイル名と、格納用配列を渡す #----------- my $cnt = &GetData("test.csv", \@l); print "COUNT -> ".$cnt; for(my $i=0; $i < $cnt; $i++){ print $l[$i]; } ################################################################## # 概   要:指定したCSVファイルをオープンしCSVデータを配列に取得する。 # パラメータ:ファイル名, CSVデータ格納用配列 # 戻 り 値:データ取得件数 ################################################################## sub GetData { my ($f, @bf) = @_; my $rcnt = 0; print "FILE NAME -> ".$f."\n"; if ( open(FP, "<${f}") ){ print "FILE OPEN -> success.\n"; @bf = split(/,/, <FP>); close(FP); $rcnt = @bf; print "CSV GET COUNT -> ".$rcnt."\n"; } return $rcnt; } -----実行結果は以下の通りです。----- D:\>perl test.pl FILE NAME -> test.csv FILE OPEN -> success. CSV GET COUNT -> 5 Use of uninitialized value in print at test2.pl line 12. Use of uninitialized value in print at test2.pl line 12. Use of uninitialized value in print at test2.pl line 12. Use of uninitialized value in print at test2.pl line 12. COUNT -> 5 -----CSVファイルの内容は以下の通りです。(ファイル名:test.csv)----- あいうえお,かきくけこ,さしすせそ,たちつてと,なにぬねの 配列の要素数が取れているので、配列内にデータは格納されているとは思っています。 出力方法をどのように正せばよいがご教示お願い致します。

    • ベストアンサー
    • Perl
  • コンパイラの作成

     皆さんのお力を貸してください.  現在, Java 言語を用いてコンパイラを作成しているのですが, 関数の引数として 1 次元配列を渡す方法 ( 配列の要素全体のコピーを渡すのではなく配列の先頭の番地を渡す方法 ) と参照渡しのプログラム記述方法が解らず悩んでおります.  何卒ご教授お願いいたします.

  • サブルーチンの返値に配列のハッシュ

    いつもお世話になっております。 HTML::Templateを使用する為、サブルーチンの返値に配列のハッシュを入れたいと思っていますが、うまくいきません。 また、myの使い方が分からず、返値までの方法も若干気になります。 よろしくお願い致します。 use HTML::Template; @loop = &loop_make('aa<>ab<>ac','ba<>bb<>bc','ca<>cb<>cc'); my $template = HTML::Template->new(filename=>'sample.html'); $template->param(loop=>\@loop); print "Content-Type: text/html\n\n"; print $template->output; exit; sub loop_make{ @aaa = (); foreach $xxx (@_) { ($one,$two,$three) = split(/<>/,$xxx); push @loop, { one => $one, two => $two, three => $three }; } return \@aaa; }

  • ハッシュのリファレンスを用いた処理

    ActivePerl 5.8 , WinXP SP2の環境です。 Perl スクリプトを用い、ファイルから複数のブロックからなる情報をよみとり、個別のハッシュを作り、それをリファレンスの配列としてまとめて後から参照するという操作をしたいのですが、詰まってしまいました。。 例として読み取るファイルは ---input.txt--------- >1 Jan 1 Feb 4 >2 Mar 9 Apr 3 >3 Oct 8 Nov 4 ------------------ ここから1,2,3の個別のハッシュ {Jan => 1 Feb => 4} {Mar=> 9 Apr =>3} {Oct =>8 Nov =>4} を作成し、それぞれのハッシュのリファレンスの配列をつくり、その後からすべてのハッシュの中身を個別に出力させたいと思いました。 次のようなスクリプトを作成したのですが思ったように作動しません。 use strict; open (IN, "input.txt") or die ("cant open file \n"); my $reff; my @array_of_reff; my %hash; my $count = 0; while(<IN>){ my $line = $_; ######ここでは各ブロックの頭の ">"を認識し、2個目以降であれば直前までで作ったハッシュのリファレンス($reff)を配列@array_of_reffに入れる。 if($line =~ /^>/){ if($count >0){ $reff = \%hash ; push (@array_of_reff, $reff); %hash = (); } $count++; } ########ここではアルファベットが入った行を認識して、ハッシュに追加しています if($line =~ /^[A-Za-z]/){           $line =~ /([A-Za-z]+)\s+/; my $month = $1; $line =~ /\s+(\d+)/; my $day= $1; $hash{$month} = $day;     } ###ここはファイルの最後になったら直前まで作っていたハッシュののリファレンス($reff)を配列@array_of_reffに入れる。 if( eof ){ $reff = \%hash ; push (@array_of_reff, $reff); } } #####ハッシュのリファレンスの配列(@array_of_reff)からもとのハッシュを参照し、ハッシュごとに出力 foreach my $reff_of_hash (@array_of_reff){    print "output";    while( (my $key,my $value) = each %$reff_of_hash ){     print "\n" , $key, " : ", $value, ;    } } このスクリプトを実行すると Nov 4 Oct 8 という3つめのハッシュのなかみが3回出力されてしまいます。自分では3つの別のハッシュをつくっているつもりでも、どうやら1種類しか作れていない、もしくはハッシュが上書きされているようなのですが、原因がわかりません。 この例だけ見るとハッシュのリファレンスを使う必要はないのですが、実際にはもうすこし大きいスクリプトで"ハッシュのリファレンスの配列を他のサブルーチンに渡す"ということを想定しており、これが解決できず先に進めない状態です。 アドバイス、解決法がわかったら教えていただけないでしょうか。

    • ベストアンサー
    • Perl
  • 初心者です。Perlではどんな時変数宣言は必要ですか?

    Perl初心者です。 マニュアル本を見ると、Perlでは特に変数を宣言しなくても扱えるようになっていますよね。 今まで幾つか自作CGIプログラムを作ってきたのですが、一度も my や localといった変数宣言を使った事がありません。 プログラム自体は正常に稼働しているので今まで全く無視していたのですが、こちらのPerlカテゴリの質問などを参照させていただいていると、皆さん必ず変数を my で宣言してらっしゃいます。 これは行った方がよいものなのですか? 宣言する事のメリット、宣言しない事のリスク、もしくはしたほうが良い場合、しない方が良い場合等を教えてください。とりあえず、サブルーチン内で宣言すると他のサブルーチンでは使えないらしい、という事だけは朧気に… よろしくお願いします。

    • ベストアンサー
    • Perl
  • Perlのサブルーチンの引数引継ぎ?

    こんにちは。 Perlの引数について質問です。 サブルーチンに引数を渡し、サブルーチンの中で他のサブルーチンをよんでいます。 すると引数を渡していないサブルーチンにまで引数が与えられてしまっているようです。 @_で受け取ると引数が渡されてしまい、$_[0]だと渡されずにすみます。 これはなぜなのでしょうか?Perlには引数を引き継ぐルールでもあるのでしょうか? 以下、サンプルです。 -------------------------------- &test('引数です'); sub test { &test2; } sub test2 { (my $hoge) = @_; } -------------------------------- $hogeに「引数です」が入ります。 &test2;を&test2();とすると大丈夫です。

    • ベストアンサー
    • Perl