sironekotoroの日記

Perl で楽をしたい

独習Perl 第2版 第7章 サブルーチン

7.1 サブルーチン

  • 最初の説明は簡単だったのに、練習問題が「ハノイの塔」
    • ファッ!?
  • うん、わからん。
# 引数1:移動元にある円盤の数
# 引数2:移動元の棒の名前
# 引数3:移動先の棒の名前
# 引数4:作業用の棒の名前
&hanoi( 3, "左", "中央", "右" );

sub hanoi {
    my ( $disk, $bar1, $bar2, $bar3 ) = @_;

    # 円盤が1つ以上残っている
    if ( $disk > 0 ) {

        # 再帰呼び出し1
        &hanoi( $disk - 1, $bar1, $bar3, $bar2 );

        # 移動内容を表示
        print "円盤 $disk$bar1 の棒から $bar2 の棒へ移動",
            "\n";

        # 再帰呼び出し2
        &hanoi( $disk - 1, $bar3, $bar2, $bar1 );

    }
}

# 円盤 1 を 左 の棒から 中央 の棒へ移動
# 円盤 2 を 左 の棒から 右 の棒へ移動
# 円盤 1 を 中央 の棒から 右 の棒へ移動
# 円盤 3 を 左 の棒から 中央 の棒へ移動
# 円盤 1 を 右 の棒から 左 の棒へ移動
# 円盤 2 を 右 の棒から 中央 の棒へ移動
# 円盤 1 を 左 の棒から 中央 の棒へ移動
  • サブルーチンで階乗を求める練習問題
    • for文とかでならすぐに作れるのに
    • 無限ループで強制終了させる事、6回
  • 自作ルーチン
    • return $sumのところをelse外に書いてしまい、しばし悩む。
my $sum = 1;    # 合計
my $num = 5;    # 階乗を求める値
print factorial($num,$sum), "\n";

sub factorial {
    my ($num,$sum) = @_;

    if ( $num > 1 ) {
        $sum *= $num;        
        $num--;
        factorial($num,$sum);
    }else{
        return $sum;
    }
}
  • 解答サンプル
    • 式の中に直接サブルーチンを入れてるのが新鮮だった。そういうのアリなのか。
    • 自分のと比べると、if文の正の条件のときではないときに式を入れてる。
      • うちの場合は先に合致する条件を考えてからif文の条件式を作ってしまうからなぁ。
      • 人のコードは勉強になる
my $number = 3;
#my $answer;
print "$number! = ", &factorial($number), "\n";

sub factorial {
    my ($number) = @_;
    my $answer;
    if ( $number <= 1 ) {
        $answer = $number;
    }
    else {
        $answer = $number * &factorial( $number - 1 );
    }
    return $answer;
}

7.2 グローバル変数とローカル変数

  • この章、use strictしてるとまともに動かなかったり
  • local変数がサブルーチン呼び出しでも使えるのは便利そう。

7.3 リファレンス

  • Perl入学式以前はまったく理解できなかったけど、おかげでなんとかわかるように。
    • Perl入学式マジ素敵
  • 無名サブルーチンの素晴らしさがいまいち分からない
    • 無名サブルーチンからの値を受けるときは&つかう
    • 無名サブルーチンって英語でなんて言うんだろ?
      • Subroutin Referances でいいんかな

7.4 ライブラリとリファレンス

  • 特定の機能を実行するための汎用性のあるサブルーチンを集めて1つのファイルにしておき、それをスクリプトに組み込む方法
  • メインルーチン開始時に実行されるBEGIN,終了時に実行されるENDという特別なサブルーチンを定義できる

ライブラリ

  • require ("lib-file")で呼び出す。
    • ファイル名にはディレクトリを含める事が出来る
  • ライブラリのスクリプトの最後に1;をつける
  • ライブラリの中でグローバル変数を定義すると、呼び出した側でもグローバル変数として扱われるので、環境設定ファイルとして利用する事も出来る

モジュール

  • use moduleおなじみ
  • 呼び出すときにディレクトリを含む事は出来ない
    • 代わりにFile::ListingというモジュールはFileディレクトリのListingというモジュールを意味する

パッケージ

  • ライブラリやモジュール内で定義した変数の上書きを防ぐ事が出来る
  • パッケージ内の変数にアクセスするときには$package-name::variableのようにアクセスする

7.5 色々なモジュール