sironekotoroの日記

Perl で楽をしたい

すぐわかる オブジェクト指向 Perl 第4章 、第5章

ハッシュスライス!

  • 「第4章 ハッシュのリファレンス」については特に引っかかりなくすらすらと
  • いや、一個だけあった、ひっかかったところ
$refMonth = {
    January   => 1,
    February  => 2,
    March     => 3,
    April     => 4,
    May       => 5,
    June      => 6,
    July      => 7,
    August    => 8,
    September => 9,
    October   => 10,
    November  => 11,
    December  => 12,
};

for( @{$refMonth}{ September, October, November } ) {
    print "autumn contains month No. $_\n";
}
  • @{$refMonth}{ September, October, November } 、普段ハッシュスライスを使わないので、初見で???だった
    • ハッシュスライスを使うべきところで、迂遠な書きかたしているなぁって思った
    • 知っていれば回避できる苦労、知らないと回避できない苦労
    • 学習大事よね

サブルーチンリファレンスがあるなら、サブルーチンは

  • 「第5章 サブルーチンのリファレンス」
  • サブルーチンもリファレンス化出来るなら、普通の(今まで学習してきた)サブルーチン構文とはいったい・・・って気持ちに
    • サブルーチンのみならず、(普通の)配列も(普通の)ハッシュも、リファレンス化したものの前座なのだろうか・・・

シグナルハンドラ

ここでは Perl であらかじめ定義された特殊なハッシュ変数 %SIG というものを紹介します。この要素にサブルーチン リファレンスを入れると、プログラムが OS の機能によってあるシグナルを受け取ったときに、そのシグナルによってサブルーチンを実行します。

  • $SIG{'INT'} = sub {print "Oh, you pushed Ctrl-C! \n"}
    • Ctrl + C を押したときに、 `SIG{'INT'} が呼び出されて、そのときハッシュの値に格納されたサブルーチンが動く、という理解で良いのかな?

この行では、ハッシュ要素 $SIG{'INT'} に無名サブルーチンを代入しています。これによって、このプログラムが sigiht をもらったときに実行する動作を定義しています

  • 通常は Ctrl + C でプログラムの実行を止める sigint になるけど、その動きを上書きして制御できると。
  • なるほど!

シュワルツ変換

  • まず名前がかっこいい
    • 大昔、シナリオシュミレーションゲームで「シュバルツシルト」ってゲームありましたなぁ
  • たしか「続・はじめてのPerl」にも出てきた
  • その時はふんふん、なるほどーで通り抜けた程度
  • しかしこの本はみっちり解説がついている
  • 詩を、各行の長さ順で並べ替えるという例題
    • その1:各行の文字列の長さを配列に入れ、それを sort
my @input = <DATA>;
my @length = ();

for (@input){
    push @length , length($_)
}

print sort {$b <=> $a} @length;
  • その2:各行そのものの文字列と、文字列の長さを配列に入れて、リファレンス化し、それを別な配列に入れる
for (@input) {
    my @lengthIndex = ();
    $lengthIndex[0] = $_;         # 文字列そのものを配列の0番目に
    $lengthIndex[1] = length($_);   # 文字列の長さを配列の1番目に
    push @length, \@lengthIndex;
}
  • その3:(その2で用意した)配列リファレンスを、文字列の長い順に並べ替えて、さらに別な配列に格納
    • 一応これで例題は解ける
my @length2 = sort {$b->[1] <=> $a->[1]} @length;
for (@length2){
    say $_->[0];
}
  • その4:最初の for 内で利用している配列を無名配列にする

    • なるほど、確かにこの @lengthIndexfor の中でしか使っていない、「使い捨て」の配列だ
    • これぞ無名配列!これこそanonymous Array !納得した!
  • その5:2回使われている foreachmap で置き換えていく

my @length = map { [ $_ , length($_) ]  } @input;
my @length2 = sort { $b->[1] <=> $a->[1] } @length;
print map {$_->[0]} @length2;
  • その6:mapUNIX のパイプのように書けるので、中間配列が不要になる
    • ついでに不要なコードブロックも外す
print map $_->[0], 
      sort { $b->[1] <=> $a->[1] }
      map [ $_, length($_) ], @input;
  • 美しいなぁ・・・