すぐわかる オブジェクト指向 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
- その1:各行の文字列の長さを配列に入れ、それを
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
内で利用している配列を無名配列にする- なるほど、確かにこの
@lengthIndex
はfor
の中でしか使っていない、「使い捨て」の配列だ - これぞ無名配列!これこそanonymous Array !納得した!
- なるほど、確かにこの
その5:2回使われている
foreach
をmap
で置き換えていく
my @length = map { [ $_ , length($_) ] } @input; my @length2 = sort { $b->[1] <=> $a->[1] } @length; print map {$_->[0]} @length2;
- その6:
map
はUNIX
のパイプのように書けるので、中間配列が不要になる- ついでに不要なコードブロックも外す
print map $_->[0], sort { $b->[1] <=> $a->[1] } map [ $_, length($_) ], @input;
- 美しいなぁ・・・