• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:サブルーチンの@_とreturn)

サブルーチンの@_とreturn

yuizuianの回答

  • ベストアンサー
  • yuizuian
  • ベストアンサー率42% (103/245)
回答No.1

まず、書かれているスクリプトに一部書き間違いと思われるところがありますので、そちらを修正しますね。 2 : $kekka_sub_1 = $sub_1($aa); 3 : $kekka_sub_2 = $sub_2($aa); は $kekka_sub_1 = &sub_1($aa); $kekka_sub_2 = &sug_2($aa); ですね。 引数というのは、関数へジャンプするときに 一緒に持っていく変数や値の事です。 たとえば、このスクリプトですと2行目、3行目の$aaの部分が引数に当たります。 Perlでは関数を呼び出すときに自動的に引数が@_という配列になります。 なので、引数は関数側ではその配列の添え字を利用して、 @_[0]  # 一つ目の引数 @_[1]  # 二つ目の引数 という感じで値を受け取るんです。 このスクリプトでは、値を受け取るときに ($aa) = @_; となっていますが、これは $aa = @_[0]; と同じ意味になります。 split関数の記述を思い出してくださればご理解いただけると思います。 でも後者の方がわかりやすいと思いますよ。 もっと言えば、このままだとこの$aaと関数を呼び出す時に使用した$aaは同じ物とみなされてしまうので、関数の中で$aaの中身を変えてしまったら、関数の外の$aaの中身も変わってしまいます。 それを防ぐ為には local($aa) = @_[0]; として、「これはこの関数の中だけで使う変数なんだ」と書いてやる必要があります。 returnですが、これは「戻り値」と言いまして、関数から抜けるときに一緒に持って変える値の事です。(この場合$aa) その値はこの例ですと$kekka_sub_2 = &sub_2($aa); の$kekka_sub_2 に格納される事になります。 sub1では受け取った値("hello")を"Hanako!"と連結させて返しているんです。 実際にこのスクリプトを動かしてみると、よくわかると思いますよ。 長々と失礼しました。

alemania
質問者

お礼

yuizuianさん、とってもとっても分かりやすい解説ありがとうございます。 ものすごく分かりやすいので、ひとつひとつ何度も読んでます。 こんな参考書があったらいいんですけど、探すのが下手なのか、それとも私が理解できなさ過ぎなのか・・・・。 とにかく、ありがとうございます。本当に助かりました。

関連するQ&A

  • サブルーチンからサブルーチンを呼び出す

    #平均を求める,サブルーチンを使用 @dat=(1,2,3,4,5,6,7,8,9,10); $mean=&mean(@dat); print "mean="; print $mean; sub mean{ $sum=&sum(@dat); $n=@dat; $mean=$sum/$n; return($mean); } sub sum{ for($i=0;$i<$n;$i++){ $sum+=$dat[$i]; } return($sum); } Perlを勉強し始めたのですがサブルーチンの所で分からない所があるので教えていただけませんか? mean関数(Perlではmeanルーチンなどと呼ぶべきでしょうか?)の中でsum関数を呼び出してデータの合計を$sumに代入したいのですが,この場合だとうまく代入されていないようなのですが,何がよろしくないのでしょうか?

    • ベストアンサー
    • Perl
  • 希望のサブルーチンを読み出すプログラムを教えてください。

     まずお断りをしておきます。  初心者なので、変な表現をしていたら申し訳ありません。  お聞きしたいのは、「複数のサブルーチンを用意しておいて、ある変数の値に対応して希望のサブルーチンが呼び出せるようにするにはどうすればよいか?」と言う事です。  プログラムはできるだけ簡単にしたいです。  無茶な書き方だと思いますが、イメージとしては以下の通りです。 (コマンドもめちゃくちゃだと思います・・・。すみません。) ******************************** MAIN------------ FOR A=0 TO 10 GOSUB A NEXT SUB------------- 0: PRINT A RETURN 1: PRINT A RETURN  ・  ・  ・ 10: PRINT A RETURN ********************************  御回答、よろしくお願いします。

  • Segmentation fault

    Cygwinにてアルゴリズムの勉強のためにC言語で コーディングしているのですが、Segmentation fault (core dumped) という言葉が出てファイルを実行できません。 試行錯誤しているのですが手に負えません。 よろしくお願いします。 #include <stdio.h> #include <stdlib.h> #define MAX_LINE 30 int main(void); int main(void){ char buffer[3]; int taro,hanako,number; int judge[4][4] = {{3,1,2,2,},            {2,3,1,2,},             {1,2,3,2,},             {1,1,1,3,},                 }; char kekka[3][MAX_LINE] = {"太郎の勝ち", "花子の勝ち", "あいこ" }; gets(buffer); taro = atoi(buffer); taro = taro-1; gets(buffer); hanako = atoi(buffer); hanako = hanako-1; number = judge[taro][hanako]; printf("じゃんけんの結果は%sです。",kekka[number][MAX_LINE]); return(0); }

  • サブルーチンについて

    下記のようなソースコードを書いたところエラーが出てしまいました。 $sum = $sample2($a); の箇所でエラーが起こっているようなのですが、解決の仕方が分かりません。 &sample1(5,'&sample2'); sub sample1 { ($a,$sample2) = @_; $sum = $sample2($a); print $sum; } sub sample2 { ($a) = @_; $b = 10; $sum = $a + $b; return $sum; } このように、サブルーチンの中に更にサブルーチンを書いて、なおかつそのサブルーチン名を一旦変数に格納して使用する場合はどのようにプログラムを書けば良いのでしょうか?? ""で囲ったりといろいろとしてもダメでした。 もちろん、$sum = $sample2($a); ではなく $sum = sample2($a); のように書けば良いとは思うのですが、一度サブルーチン名を変数に入れてから使用する場合はどのようにすれば良いのでしょうか?? ご回答の程よろしくお願い致します。

    • ベストアンサー
    • CGI
  • サブルーティンの使い方。

    サブルーティンの理解を深めるために、 階乗の計算をサブルーティンで行うプログラムを作りました。 自作のプログラムについて質問を二つしたいと思います。 1.一応、計算は出来るのですが、 定型的でないというか、無駄が多いというか、 何か違う気がするのです。 どこか変なところはありませんでしょうか? 2.エラーメッセージをどこにいれたらいいのかわかりません。 数字以外、(例えば文字)が入力されれば1が出力されるようにはしたのですが、 「これは数字ではありません」のようなエラーメッセージを出したいのです。 この場合はどこにどのように記述すればいいですか? 色々試してみたのですが、思い通りに動きませんでした。 みなさま、知恵をお貸しください。 ------------------------------------------- use strict; print "数字を入力してください。\n"; chomp( my $number = <STDIN> ); my $k_number = kaijo($number); print "入力された数字の階乗は$k_numberです。\n"; sub kaijo { my $number = shift @_; return undef if $number < 0; return 1 if $number == 0; my $kaijo = 1; for(my $i = $number; $i>1; $i--) { $kaijo *= $i; } return $kaijo; }

  • サブルーチン内のサブルーチン定義について

    サブルーチン内で定義したサブルーチンで、思い通りにならない挙動で困っています。 'test'を10万回繰り返す文字列の生成を行い、その文字列長を表示する関数を funcA とします。その生成過程では、自分の関数内で宣言した再帰関数 funcB を呼び出します。 #! /usr/local/bin/perl use strict; my $time0; for(my $i=0; $i<10; $i++){   $time0 = times();   &funcA();   print((times() - $time0). "\n"); # funcAに掛かった時間 } sub funcA {   my $buffer = '';   &funcB(1);   print length($buffer) . " : "; # $buffer の文字列長      sub funcB{     my $n = shift;     $buffer .= 'test';     return if($n==100000);     funcB($n+1);   } } この結果が、 400000 :3.063 0 :0.468 0 :0.594 0 :0.766 0 :0.859 0 :1.11 0 :1.187 0 :1.141 0 :1.343 0 :1.469 となり、初回以降 $buffer の長さが0となるのも不可解ですが、funcA の実行時間が増加していくのも理解できません. これを #! /usr/local/bin/perl use strict; my $time0; my $buffer; # 注1 $buffer をファイル内大域変数として宣言 for(my $i=0; $i<10; $i++){   $time0 = times();   &funcA();   print((times() - $time0). "\n"); } sub funcA {   $buffer = ''; # 注2 レキシカル変数宣言をやめた   &funcB(1);   print length($buffer) . " : ";      sub funcB{     my $n = shift;     $buffer .= 'test';     return if($n==100000);     funcB($n+1);   } } とすると、結果は 400004 :3.188 400004 :0.234 [以降、上にほぼ同じ] と文字列長は正しいものの,初回以降のfuncA実行時間が極端に減ります. 内部ではどういうことが起こっているのでしょうか.

    • ベストアンサー
    • 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
  • Perlです。サブルーチンについて

    以下の文はあっていますでしょうか。 # サブルーチンを呼び出して引数は 3 とする。 # そして返ってきた戻り値を変数$aに代入せよ。 $a=&a(3); # サブルーチン名aせよ。 sub a{ # $_[0]が引数 3 となりプラス1して変数$bに代入せよ。 $b=$_[0]+1; # 変数$bの内容を戻り値として返せ。 return $b; } # 変数$aの内容を表示せよ。 print "$a";

    • ベストアンサー
    • Perl
  • AUTOLOADサブルーチンが実行される条件?

    Perlのコードを動かしながら勉強していて、ふと納得いかない点があったので教えてください。 次のコードを実行すると'0'と表示されます。 Cls->new; package Cls; sub new {bless([])} sub AUTOLOAD {print(0)} つまりAUTOLOADサブルーチンが実行されているようです。 しかし私のコードの中ではAUTOLOADサブルーチンの定義はしているものの、どこからも呼び出していません。 このコードは何も行わずに終了するはずなのですが、そうではありませんでした。 AUTOLOADサブルーチンは、いつ、どこで、何者によって呼び出されるのでしょうか。

    • ベストアンサー
    • Perl
  • use baseしたpackageのローカル変数の書き換え

    packageを継承した場合、 継承先(以下のMyPkg)で継承もと(MyBase)のローカル変数($localValue)を直接書き換える方法はありませんか? package MyBase; my $localValue; sub doBase{ my $self=shift; $localValue ={ 'hanako'=>{'id'=>1, 'pref'=>'tokyo'} }; } sub getPref { my $self=shift; my $name=shift; $localValue->{$name}{'pref'}; } package MyPkg; use base qw(MyBase); sub new{ my $class=shift; my $self={}; bless $self, $class; return $self; } sub doAnything { # この中でMyBaseの$localValueを直接書き換えたい $localValue ={ 'taro'=>{'id'=>2, 'pref'=>'osaka'} }; } ------main:: my $pkg=new MyPkg; $pkg->doSomething; print $pkg->getPref('hanako'); $pkg->doAnything; print $pkg->getPref('taro'); ---------- 以下のような感じでmyBaseの中に$localValueを返すサブルーチンを作っておけば、 print $pkg->localValue->{'hanako'}{'pref'}; などと取得は出来ますが、 $pkg->localValue->{'hanako'}{'pref'}='kyoto'; のような代入は無理みたいでした。 package MyBase; my $localValue; sub localValue{ my $self=shift; $localValue; } doBaseのようなサブルーチン経由で書き換えていますが、 use baseしていても、やはりそうしないとダメでしょうか。 Windows、ActivePerl、perl 5.10.0 Linux、Perl5.8