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

Perlのサブルーチン 学習メモ

2022-01-28 09:57:42

I. 定義

関数は、システム関数とユーザー関数に分けられます。サブルーチンは特定のタスクを実行する独立したコードで、コードの繰り返しを減らし、プログラムを読みやすくします。サブルーチンはPERLではプログラムのどこにでも出現させることができます。それらは、次のように定義されます。

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

  sub subroutine{
    statements;
  }

II. インヴォケーション 
  呼び出し方法は以下の通りです。
1. &コールで呼び出す
コピーコード コードは以下の通りです。

  &subname;
  ...
  sub subname{
    ...
  }

2. 2. 定義してから呼び出す場合は、& の記号を省略することができます。
コピーコード コードは以下の通りです。

  sub subname{
    ...
  }
  ...
  subname;

この方法をお勧めします。
3、前方参照、サブルーチン名を先に定義し、後からサブルーチン本体を定義する。
コピーコード コードは以下の通りです。

  sub subname;
  ...
      subname;
  ...
  sub subname{
    ...
  }

4. doで呼び出す
  do my_sub(1, 2, 3); は &my_sub(1, 2, 3) と同じ意味です。
iii. 返り値 
  デフォルトでは、サブルーチンの最後のステートメントの値が戻り値として使用されます。return (retval); というステートメントは、サブルーチンを起動し、リストであるretvalという値を返すことも可能です。
IV. ローカル変数 
  サブルーチン内でローカル変数を定義するには、myとlocalの2つの方法があります。myで定義された変数はそのサブルーチン内にのみ存在し、localで定義された変数はメインプログラムには存在せず、そのサブルーチンとサブルーチンから呼ばれたサブルーチンに存在するという違いがあります(PERL4にはmyは存在しません)。これらは定義された時点で値を割り当てることができ、例えば
コピーコード コードは以下の通りです。

  my($scalar) = 43;
  local(@array) = (1, 2, 3);

V. サブルーチン・パラメータ渡し
1. 形状
コピーコード コードは以下の通りです。

  &sub1(&number1, $number2, $nubmer3);
  ...
  sub sub1{
    my($number1, $number2, $number3) = @_;
    ...
  }

2. 配列の転送
コピーコード コードは以下の通りです。

  &addlist (@mylist);
  &addlist ("14", "6", "11");
  &addlist ($value1, @sublist, $value2);
  ...
  sub addlist {
    my (@list) = @_;
    ...
  }

引数が配列の場合、サブルーチンでは1つの配列変数にのみ代入されます。例えば
コピーコード コードは以下の通りです。

  sub twolists {
    my (@list1, @list2) = @_;
  }

は必然的に空になります。しかし、単純な変数と配列変数の両方を渡すことができます。
コピーコード コードは以下の通りです。

  &twoargs(47, @mylist); # 47 is assigned to $scalar, @mylist is assigned to @list
  &twoargs(@mylist); # The first element of @mylist is assigned to $scalar and the rest to @list
  ...
  sub twoargs {
    my ($scalar, @list) = @_;
    ...
  }

VI. 再帰的サブルーチン

  PERLでは、上記と同じようにサブルーチン同士を呼び出すことができ、サブルーチン自身が呼び出されると再帰的サブルーチンとなる。再帰的サブルーチンには2つの条件がある。1)サブルーチンが変更しない変数以外はすべてローカル変数であること、2)サブルーチンには呼び出し自体を停止させるコードが含まれていること。

VII. エイリアスによる配列引数の受け渡し

1. メソッド &my_sub(@array) を前述のように呼び出すと、配列 @array のデータをサブルーチン内の変数 @_ にコピーするので、配列が大きくなるとリソースと時間がかかりますが、別名で渡すとこの作業がなく、その配列に対して直接操作することが可能です。形式は次のようになる。

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

  @myarray = (1, 2, 3, 4, 5);
  &my_sub(*myarray);
  sub my_sub {
    my (*subarray) = @_;
  }

2. この方法は、C言語の配列の開始アドレスにポインタを渡すのと似ていますが、同じではありません。配列の別名を定義した後、同じ名前の単純な変数があれば、その変数に対しても機能します。例えば
コピーコード コードは以下の通りです。

  $foo = 26;
  @foo = ("here's", "a", "list");
  &testsub (*foo);
  ...
  sub testsub {
    local (*printarray) = @_;
    ...
    $printarray = 61;
  }

  サブルーチンの実行が終了すると、メインプログラムの$fooの値は61になり、26ではなくなっています。
3. aliasメソッドで複数の配列を渡すことができます。
コピーコード コードは以下の通りです。

  @array1 = (1, 2, 3);
  @array2 = (4, 5, 6);
  &two_array_sub (*array1, *array2);
  sub two_array_sub {
    my (*subarray1, *subarray2) = @_;
  }

このサブルーチンでは、subarray1 は array1 のエイリアス、subarray2 は array2 のエイリアスです。
VIII. 定義済みサブルーチン 
  PERL5では、特定の時間に実行される3つのサブルーチンが予め定義されています。BEGINサブルーチンはプログラムの開始時に、ENDサブルーチンはプログラムの終了時に、AUTOLOADサブルーチンはサブルーチンが見つからない時に呼び出されます。これらを自分で定義することで、特定の時間に目的の動作を実行することができます。例えば
コピーコード コードは以下の通りです。

  BEGIN {
    print("Hi! Welcome to Perl!\n");
  }
  AUTOLOAD{
    print("subroutine $AUTOLOAD not found\n"); # Variable $AUTOLOAD is the name of the subroutine that was not found
    print("arguments passed: @_\n");
  }

  同じ定義済みサブルーチンに対して複数の定義済みサブルーチンが定義されている場合、BEGINは順次実行され、ENDは逆順に実行されます。