• ベストアンサー

サブルーチンの引数の、呼び出し側の呼称を得る

サブルーチンの呼び出し、例えば sr($p); という呼び出しがあった場合、サブルーチンsb()の中で、引数は@_として扱われて、  $p の値などは  $_ で知ることが出来ます。 それではサブルーチンsb()の方から、  $_ が呼び出し側で何と呼ばれているか知ることは出来るのでしょうか? つまり、この場合、$_は呼び出し側で  $p と呼ばれているわけですが、この呼称をサブルーチン側で知ることは出来るでしょうか。

  • Perl
  • 回答数5
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
  • kabaokaba
  • ベストアンサー率51% (724/1416)
回答No.4

そもそもサブルーチン内で 呼び出しもとの実引数の「変数名」を 「本当に必要」な状況そのものを想像できません. 質問の文面とものの言い方から初心者さんではないようなので もしかするとものすごい状況にいるのかもしれませんが・・・ そうすると,以下に書くようなことは とっくに検討済みの可能性もありますね サブルーチンの中で呼び出しもとの変数をいじりたいのであれば $a=10; sub { $_[0]++ }->($a); print $a; とかすれば,可能ですね(Perlはcall by referenceだから). もっともこれは,具体的な値そのものを渡せばエラーになります. ただ「参照渡し」なので,$_[0]と呼び出し元の変数の 実体は同じ,つまり,\$_[0]と\$aは同じだから \$_[0]と同じ値を持つものをシンボルテーブルから 無理やり探し出すことは可能だと思われます. $a=10; sub {foreach $val (values %main::){ *glob=$val; $temp=$val; if (\$_[0]==\$glob) { $temp=~s/\*main:://; print "argument: \$$temp\n" } } } ->($a); こんな感じ. ただし,シンボルテーブルを読んでるわけだから, レキシカルな変数は相手にできませんし, この例だと引数はスカラであることが前提です. けど,リファレンスを渡してあげれば,細工すれば スカラ以外でも処理できるでしょう. けど,シンボルテーブルで遊ぶ以外の意味はなさげです. なお,これは具体的な値を渡すと何も出力されませんし, レキシカルな変数を相手にするにはどうすればいいでしょうね? 「レキシカルな変数のシンボルテーブル」? BモジュールとかPadWalkwerとかの「黒魔術の世界」に 浸ればできるのかもしれませんが,私レベルでは分かりません. #use strictとの両立方法・・・わかりません. いっそのこと,引数そのものに もっと細かい情報を持たせるというのもありかもしれません. Scalar::Utilのdualvar関数を使って 自分自身の情報を変数にもたせるというのもありかも. もしかするとattributeを利用してもいいのかも #この段落の内容は実験してない想像にすぎません. そして,「変数名」を取得して, サブルーチン内で「ソフトリファレンス」したいのでしょうか? つまり, $fred = 23; $varname = "fred"; ++$$varname; というようなことをしたいということでしょうか? これは,perldoc perfaq7で How can I use a variable as a variable name? の項目をよめば 「Beginners often think」で 「very bad idea」だと詳細な説明があります. こんなことは先刻承知かもしれませんが. まあ,なにはともかく >人間的にみれば第1引数に第2引数の情報は全て入っているのに これには私も同意しませんけどねえ. 仮に「人間的に入ってても」そもそもPerlは人間じゃないですし, すべての情報が入っててもそれが渡されるわけではないですな. それと >このコーディングは私の無知を象徴することになってしまうので、 無知をさらけ出すよりも メンテナンスや拡張が困難なコードを残すほうが 私はいやです. #というか・・・Perlじゃないけど #メンテナンス困難なコードのバグ取りを #よくさせられるから・・・ メンテナンス不可の簡潔なコードよりも メンテナンスが楽な可読性の高い冗長・饒舌なコードのほうが ずっといいとおもうのは私だけではないと思います.

makoji
質問者

お礼

ご教授、ありがとうございます。 前回の私の態度には問題があったかもしれません。お詫びします。アラシのような行為(人を小馬鹿にしたような文面で、分かり切ったtypoの指摘をしたり関係ない質問をするけど、でも実質的な話は進まない。)にムカついていました。 今回はデバッグツールを自作しようと思った次第です。 プログラム中にデバッグ関数を書きいれて、その位置における変数の値を知るに際して、その関数がファイル名、行番号、変数名を自動で記述してくれたら助かると思いました。 ご教授いただいだPadWalkerモジュールを用いました。 peek_my()のrefをとってmy変数かour変数かを調べる。 our変数だったらpeek_our変数でオブジェクトを生成し直す。 生成したオブジェクトに対して、連想配列、配列、スカラーに場合分けして、値を書きだす。 この場合、値や式を引数に取れません。リファレンスも無理だと思います。そういったところが使い勝手が悪いですが、そういう特殊用途向けにはコメントを手動で記述する関数がありますので、そちらと併用しようと思います。 助かりました。 どうもありがとうございます。

その他の回答 (4)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

いちおう #3 の時点で「シンボルテーブルを読む」のは想定したんですけど, *b = \$a; とされてしまうと「シンボルテーブルを読んでも $a と $b を区別することができない」のであきらめました>#4. っつ~か, この状況で $a と $b を区別する意味が私にはわかりませんが. そういう意味で「変数名が必要な状況」がわからないというのは同意. ALGOL ならよかったのにね.

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

では結論だけ: 1つの引数だけで知る方法はありません. リファレンスだろうとなんだろうと, できないものはできません. 「人間的にみれば第1引数に第2引数の情報は全て入っている」というのが既に間違っているので....

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

sr(7); という呼び出しの場合には何を知ればよいということになるのでしょうか? そして sr(4+3); のときは?

makoji
質問者

補足

今問題にしているのは、変数を引数にした場合に、その変数の値ではなく呼称を得ることが出来るかという問題であって、値そのものを引数にした場合に、その呼称をどう扱うべきかは、次の問題です。そういう補足を求めてこられるということは、Tacosanさんの中で、当初の題意は解決済みということですが、それはどのような方法なのでしょうか。 引数に連想配列や配列をそのまま指定した場合、サブルーチン側ではそれは全て  @_ として扱われるから、引き渡された変数が連想配列であるか配列であるか分からなくなります。つまり引数の頭に「@」が付いているのか、「%」が付いているのかすら、サブルーチン側では判別できないということかと。 でもリファレンスで送ればこの問題は解決するわけです。さらにサブルーチンの引数を一つ増やして、例えば  sr(\@a,'a') のようにしてあげればサブルーチン側で、引数が呼び出し側で「@a」と呼ばれていたのだと理解できます。 ただ人間的にみれば第1引数に第2引数の情報は全て入っているのに、あらためて第2引数でその情報を渡すというのは馬鹿らしく、もし第1引数だけで題意が適うならば、このコーディングは私の無知を象徴することになってしまうので、だから念のために、皆さんにご教授をお願いしている次第です。 やはりこれが最良の方法なのでしょうか。

回答No.1

> サブルーチンの呼び出し、例えば > sr($p); > という呼び出しがあった場合、サブルーチンsb()の中で、引数は@_として扱われて、 sb?srじゃないんですか? >  $p > の値などは >  $_ > で知ることが出来ます。 $_?$_[0]の間違いじゃないですか?

makoji
質問者

補足

その通りです。 typo、気をつけます。

関連するQ&A

  • Perlのサブルーチンの引数引継ぎ?

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

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

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

    • ベストアンサー
    • Perl
  • Fortranのサブルーチン引数について

    他人が作ったFortran(恐らくFortran77)のプログラムで計算をしようとしています。 コンパイルはできるのですが,実行するとエラーが出てしまい困っています。 エラーメッセージは 「forrtl:severe(157):Program Exception - access violation」 となっていて,実行時エラー番号で調べると 「プログラムが適切な参照権を持っていない仮想アドレスに書き込み,または読み取り を行おうとした」と出ていました。 Fortran初心者の自分にはイマイチ意味が判らないのですが,エラーが出た後に サブルーチンのある決まった場所に黄色い矢印が示されます。 そこで今,その部分のサブルーチンを確認しているところです。 前置きが長くなってしまいましたが サブルーチンの中を確認している途中で疑問に思った所が一つあります。 問題のサブルーチンは --------------------------------------- call dbesl(EN,0,BX0,BY0,BI0,BK0)     subroutine dbesl(X,NOR,BX,BY,BI,BK) FN = NOR  ・  ・  ・ 11 NOR = FN               <---この行に黄色い矢印が出る return end --------------------------------------- となっているのですが,サブルーチンを呼び出すcall文の所で 2つ目の引数が『0』となっているのは正しい使い方なのでしょうか? どうもサブルーチン内の計算をしてメインプログラムに引数を返す所が おかしいような気がしています。 因みにメインプログラムに戻る際の"FN"の値は『0』となっていました。 コンパイラはCompaq Visual Fortranを使用しています。 足りない情報は出来るだけ追記していきますので,ご教示宜しくお願いします。

  • エクセルマクロのサブルーチン引数で配列を使用したい

    VBA初心者です。 エクセルのマクロを組んでいるですが、サブルーチンの引数を配列にしたいのですが、どうすればよろしいでしょうか? 下記に例を示します。 呼び出し(Call)とサブルーチンの配列変数の記載方法がわかりません。 特に気になるのは、サブルーチンの配列に配列数(下記であれば10)を記入する必要があるのか? 必要な場合、元の配列数を変更した場合、どうすればミスなく、漏れなく修正できるか、良い方法はありまんせんか? (例) (呼び出し側) Dim AA(10) As Integer Call Test(AA)     ← 引数はAAでよい?それともAA() Sub Test(ByRef AA As Integer) ← AA or AA() or AA(10) ? AA(3) = AA(2) + AA(1) 以上、お手数をおかけしますが、よろしくお願いします。

  • サブルーチンに引数を2つ以上渡したい

    Access2002、vba上で サブルーチンに引数を2つ指定したいのですが、 なぜか「コンパイルエラー 修正候補=」 と出てしまいます。 引数を1つにするとうまく動作します。 どなたかお分かりの方いらっしゃいましたら教えて ください。 宜しくお願いします。 サンプルコード: -------------------------------- the_subroutine(a, b) ' ※ここでコンパイルエラー Sub the_subroutine(c As String, d As Object) End Sub -------------------------------

  • サブルーチンについて

    サブルーチンについての質問です。 サブルーチンの中で設定した変数が、そのサブルーチンを呼び出す度に初期化されてしまいます。 (例えば初めてサブルーチンを呼び出し、そのサブルーチンを抜ける時にはx=10と記憶されているのに、また次にそのサブルーチンが呼び出される時には、x=0となっている。) これをx=10のまま記憶させておき、引き続きサブルーチンの中でこの値を使う事は不可能なのでしょうか? 乱文で申し訳ありませんが、よろしくお願いいたします。

  • サブルーチンについて

    サブルーチンについて教えて頂きたいのですが HTMLからPOSTされる複数のデータ(Key=A&値=B…)をkeyごとにサブルーチンの引数 として渡したいのですが、現在は「&ReadParse」を使って$inから値を取り出しています。 ただ数十個の値が一度にPOSTされる為、下記のコードをひたすら書く感じになってしまう のかな…と思ってお尋ねしております。 それから、サブルーチンからの戻り値を、フォームに(Key=A&値=B…)の感じで返したいのですが どうすればいいのでしょう。 @pairs = ($in{'val1'},$in{'val2'},$in{'val3'},$in{'val4'},$in{'val5'}); ($para1,$para2,$para3,$para4,$para5) = @pairs; $values = func($para1,$para2,$para3,$para4,$para5); 私自体、Perl初心者でわかっていない為、なにか方法があれば教えて下さい。宜しくお願いしますm(__)m

    • ベストアンサー
    • Perl
  • サブルーチンについての質問デス

    サブルーチンについての質問です。 サブルーチンの中で設定した変数が、そのサブルーチンを呼び出す度に初期化されてしまいます。 (例えば初めてサブルーチンを呼び出し、そのサブルーチンを抜ける時にはx=10と記憶されているのに、また次にそのサブルーチンが呼び出される時には、x=0となっている。) これをx=10のまま記憶させておき、引き続きサブルーチンの中でこの値を使う事は不可能なのでしょうか? 乱文で申し訳ありませんが、よろしくお願いいたします。

  • サブルーチンの使い方

    以下のプログラムを解読中ですが、いまいち理解できません。C言語の経験はあるのですが、Perl初心者のため、Perlの文法を中心に、以下のポイントについて教えてください。 (1)この関数で、引数が「&@」となっていますが、この&の意味は「サブルーチン」ということですか?? (2)2行目のmy ($block, @listin) = @_ で各$block, @listinに格納される値を教えてください。「@_」を調べてみたところ、「サブルーチンの引数を代入」とあるのですが、ここでは、map_block(&@)の&@が&blockと@litinに代入されるということですか??そもそも&@とは何でしょうか? (3)4行目のpush @listout, &$block() for (@listin) について、push関数を調べてみたところ、配列の最後尾に値を格納するということですが、&$block() for (@listin) の部分の意味がよくわかりません。どのような値が、配列listoutに格納されるのでしょうか? (解読中のプログラム) 1sub map_block (&@) { 2   my ($block, @listin) = @_; 3 my @listout = (); 4 push @listout, &$block() for (@listin); 5 return @listout; 6}

    • ベストアンサー
    • Perl
  • GCCで関数の引数が渡らない

    gcc Ver2.9 でSH-2の開発をしています。 通常に関数を作成し、引数を渡しているのですが、引数が渡らないという現象が起きています。 現象は、 1.引数はポインタではなく値渡しである 2.引数の値が0の時だけ正しく渡らない。値が0以外の時は正常にわたる 3.引数の型は一致している 4.引数は複数あるが、後半のいくつかがだめ(何個とまでは詳しく調べていません) 5.ある特定の関数の特定の呼び出しのみがだめで全てだめというわけではない 6.コンパイルオプションに -m2 をつけるとだめだが、-m1 オプションだと問題ない 7.最適化オプションをなくしても同じだった といった状況です。 上記5からある特定の記述方法とか順序になるとだめになるのではないかといろいろ試してみたのですが見つけられません。6から記述方法に誤りがあるとも考えにくい状況です。コンパイラのバグといって片付けていいものなのかどうかです。どなたか同じような経験をされた方はいらっしゃいませんか。また関数呼び出しの場合、コンパイラがどうやって引数を渡すかご教授願えませんか。