sub func { return 100; }
みたいなサブルーチンがあった時に,
say(func - 99);
みたいな感じで呼び出すと,パッと見 1 が出力されそうに見えるが,実際は 100 が出力される.
これは - 99 が func の引数として解釈されて食われるためである. B::Deparse するとわかりやすい.
$ perl -MO=Deparse func.pl
sub func {
use warnings;
use strict;
use feature 'say';
return 100;
}
use warnings;
use strict;
use feature 'say';
say func(-99);
func.pl syntax OKここから,二項演算子としての振る舞いを期待していた - が 99 と結合して単項演算子として扱われ, -99 が引数として扱われているのが読み取れる.
もちろん,サブルーチン呼び出し時にかっこを付けて
say(func() - 99);
という感じで呼び出してやれば当初の期待値である 1 が表示されるようになる.もしくはプロトタイプを利用する方法もある.
sub func () { return 100; }
このように引数を取らないことをプロトタイプで明示すると,サブルーチン呼び出し時にかっこを付けなくても後続の値が引数として解釈されることはなくなる.その場合の B::Deparse の結果は以下のようになる.明解.
$ perl -MO=Deparse func.pl
sub func () {
use warnings;
use strict;
use feature 'say';
return 100;
}
use warnings;
use strict;
use feature 'say';
say func - 99;
func.pl syntax OKこれらは基本的な挙動ではあるのだけれど,日々を生きているとたまにハマりがち.例えば Time:Piece と Time::Seconds をあわせて使ったときなんかに
use Time::Piece; use Time::Seconds qw/ONE_HOUR/; my $t = localtime - ONE_HOUR; say $t;
などと書こうものなら,結果が Thu Jan 1 08:00:00 1970 というふうになり破滅する.localtime(-ONE_HOUR) となるからだ.
普段,perlの組み込み関数の時は (基本的に) かっこを付けずに記述するスタイルで書いていたので,組み込み関数である localtime をその感覚で使っていたところ綺麗にハマってしまった. *1
いままでは割と野生の勘みたいな感じでこのへんの諸問題を回避していて,「そういう掟なのじゃ」という感じで生活していたんですが真面目に B::Deparse とかで調べてみると色々学びがあるものですね.
*1:Time::Pieceはlocaltimeをoverrideするから最早組み込み関数ではないんでは? という意見はあると思いますが