パッケージ越しのソートサブルーチンがうまく働かない
Perlのソートサブルーチン(ソート定義サブルーチン)が次の「Case C: パッケージ越しのソートサブルーチンの利用」でうまく働いてくれません。
ソース
#!/usr/bin/perl use strict; my $by_num = sub{ $a <=> $b; }; ############################################ # Case A: 通常のソートサブルーチンの利用 print 'Case A: ', join(', ', sort $by_num (3, 6, 2, 4, 5)), "\n"; ############################################ # Case B: サブルーチンを介したソートサブルーチンの利用 sub sort_test_b{ my $by_num = shift; print 'Case B: ', join(', ', sort $by_num (3, 6, 2, 4, 5)), "\n"; }; &sort_test_b($by_num); ############################################ # Case C: パッケージ越しのソートサブルーチンの利用 { package SortTest; sub sort_test_c{ my $by_num = shift; print 'Case C: ', join(', ', sort $by_num (3, 6, 2, 4, 5)), "\n"; }; } SortTest::sort_test_c($by_num);
実行結果
Case A: 2, 3, 4, 5, 6
Case B: 2, 3, 4, 5, 6
Case C: 3, 6, 2, 4, 5
考察
$by_numのサブルーチンの中にprintを入れて検証してみましたが、どうやらCase Cでは$a、$bがundefになっているようです。なにかヒントはないかと思い、『初めてのPerl』を読み直してみました。
本当のことを話せば、sortの呼び出しの回りを取り囲んだプライベートなブロックの中で、Perlがlocal($a, $b)を実行したかのようになります。なぜなら、これらの変数は、実際にはレキシカル変数ではなく、グローバル変数だからです。(中略)ソートサブルーチンの中では、どこから来たかは気にせずに、素直に$aと$bを使いましょう。またさらに付け加えるならば、もしスコープのどこかにレキシカル変数$aまたは$bがあると、このサブルーチン定義はうまく動作しません。
初めてのPerl 第3版 p.259
どうやら、$a, $bはグローバル変数として動作しているようなので、パッケージを越えてしまうと正常に動作しないようです。