1. ホーム
  2. スクリプト・コラム
  3. パール

perlでサブルーチンの引数を参照(渡す)する2つの方法

2022-02-02 17:29:16

以下はその一例です。

コピーコード コードは以下の通りです。

use strict;
# Here are two arrays
my @i =('1','2','3');
my @j =('a','b','c');

# Before we do the processing, let's print them out and see what they look like
print "In main program before calling subroutine:i=". "@i\n";
print "In main program before calling subroutine:j=". "@j\n";

# Then we process it through the subroutine
reference_sub(@i,@j);
print "In main program after calling subroutine:i=". "@i\n";
print "In main program after calling subroutine:j=". "@j\n";
# Here is the subroutine
sub reference_sub
{
 my (@i,@j)=@_;
 print "In subroutine:i=". "@i\n";
 print "in subroutine:j=". "@j\n";
 # Here we are using pop, and shift for @_
 push(@i,'4');
 shift(@j);
}


得られた結果は以下の通りです。
コピーコード コードは以下の通りです。

F:\>perl\a.pl
In main program before calling subroutine:i=1 2 3
In main program before calling subroutine:j=a b c
In subroutine:i=1 2 3 a b c
in subroutine:j=
In main program after calling subroutine:i=1 2 3
In main program after calling subroutine:j=a b c
F:\>

この例では、サブルーチンは2つの引数@iと@jを持っています。この2つの引数をサブルーチンに渡すと、サブルーチンはそれらをすべて組み込み配列@_に入れ、@_の中に@iと@jの違いがない、つまり@_の中に混在して区別がつかなくなります。もう一度両方を取得しようとすると、@i = 1 2 3 a b c となり、@j は空になってしまうのです。多くの場合、これは明らかに私たちが望む結果ではないので、参照渡しを使います(ビッグ・キャメル本の第6章では、quot;incoming reference"と訳されています)。
コードに1つだけ変更を加えるだけです。
その手順は以下の通りです。
コピーコード コードは以下の通りです。

use strict;

# Here are two arrays
my @i =('1','2','3');
my @j =('a','b','c');

# Before we do the processing, let's print them out and see what they look like
print "In main program before calling subroutine:i=". "@i\n";
print "In main program before calling subroutine:j=". "@j\n";

# Then we process it through the subroutine
reference_sub(\@i,\@j);# where we add the backslash, or pass byreference (pass byreference, translated in chapter 6 of the Big Camel book)
print "In main program after calling subroutine:i=". "@i\n";
print "In main program after calling subroutine:j=". "@j\n";
# Here is the subroutine
sub reference_sub
{
 my ($i,$j)=@_;# references are also a special form of data, they are stored as scalar variables in @_
 print "In subroutine:i=". "@$i\n"; So here when we refer to them, we add two symbols in front of them, @ for this is an array and $ for it is a secondary reference.
 print "in subroutine:j=". "@$j\n";
    print "In subroutine:the third element is $$j[2]\n";# When referencing an element in the array the first $$ and the subsequent j[2] represent the third element in the array, while the second $$ represents the secondary reference
 # Here we use pop, and shift for @_
 push(@$i,'4');
 shift(@$j);
}


その結果は以下の通りです。
コピーコード コードは以下の通りです。

F:\>perl\a.pl
In main program before calling subroutine:i=1 2 3
In main program before calling subroutine:j=a b c
In subroutine:i=1 2 3
in subroutine:j=a b c
In subroutine:the third element is c
In main program after calling subroutine:i=1 2 3 4
In main program after calling subroutine:j=b c
F:\>

という最終結果を観察することができます。
これは、サブルーチンの中で配列に対して行ったプッシュとシフトの操作が、メインプログラムの中で機能したことを意味しています。
なぜ、このようなことが起こるのでしょうか?
一般的に、サブルーチン内で変数をマイ宣言しているため、サブルーチン内でのみ動作し、メインプログラムでは値が変化しないようになっています。
ここでは、そのバックアップではなく、本当のパラメータであるメインプログラムの値を参照しているので、それに応じて変更されることになります。