$aと$bを使うときに気をつけること

sortで使う、$a$b特殊パッケージ変数なので、
同じブロック内でsortを使うときは気をつける必要がある。(*1)

特殊パッケージ変数」っていう単語は、ここから。
$a – perldoc.jp

まずは、なんでもないコードから。

use strict;
use warnings;
use v5.10;

main();

sub main {
    say join ',', sort { $b <=> $a } 0..5;
}

実行結果はこんな感じ。
$ perl aaa.pl
5,4,3,2,1,0

次に、myを使って宣言する。

use strict;
use warnings;
use v5.10;

main();

sub main {
    my ( $a, $b ) = ( 5, 10 );
    say join ',', sort { $b <=> $a } 0..5;
    say "( \$a, \$b ) = ( $a, $b )";
}

これが、perldocに書かれていた、やってはいけないこと。
$ perl bbb.pl
Can't use "my $b" in sort comparison at bbb.pl line 9.

localを使って宣言した場合は?

use strict;
use warnings;
use v5.10;

main();

sub main {
    local ( $a, $b ) = ( 5, 10 );
    say join ',', sort { $b <=> $a } 0..5;
    say "( \$a, \$b ) = ( $a, $b )";
}

これは、問題なし。
$ perl ccc.pl
5,4,3,2,1,0
( $a, $b ) = ( 5, 10 )

ourを使って宣言した場合は?

use strict;
use warnings;
use v5.10;

main();

sub main {
    our ( $a, $b ) = ( 5, 10 );
    say join ',', sort { $b <=> $a } 0..5;
    say "( \$a, \$b ) = ( $a, $b )";
}

これも、問題なし。
$ perl ddd.pl
5,4,3,2,1,0
( $a, $b ) = ( 5, 10 )

じゃぁ、何も付けない場合は?

use strict;
use warnings;
use v5.10;

main();

sub main {
    ( $a, $b ) = ( 5, 10 );
    say join ',', sort { $b <=> $a } 0..5;
    say "( \$a, \$b ) = ( $a, $b )";
}

すでに存在する$a$bを書き換えただけなので、
もちろん、問題なし。
$ perl eee.pl
5,4,3,2,1,0
( $a, $b ) = ( 5, 10 )

最後に、違うブロックでmyを使って宣言した場合。

use strict;
use warnings;
use v5.10;

main();
foo();

sub main {
    say join ',', sort { $b <=> $a } 0..5;
}

sub foo {
    my ( $a, $b ) = ( 5, 10 );
    say "( \$a, \$b ) = ( $a, $b )";
}

これなら、問題なし。
$ perl fff.pl
5,4,3,2,1,0
( $a, $b ) = ( 5, 10 )

という訳でまとめると、
my$a$bを宣言しちゃうと、
localで退避できないのでエラーになると考えれば、
とりあえず、納得はできる。
でも、なんで$a$b使ったの?ってなるけど、
これはPerlのソースに、ハードコーディングされているらしいので、
それじゃ、仕方ないですね。(*2)

おしまい。

(*1) akiymさん++
(*2) aloelightさん++

Leave a Comment