オーバーロードとかCORE::GLOBALとか
最初はオーバーロードが分からなかったから試してた。
そのうち変なことをし始めた。
オーバーロード編
% perl -le 'use overload q{""} => sub {die};$x = bless {}; print $x' Died at -e line 1. % perl -le 'use overload q{""} => sub {1};$x = bless {}; print $x' 1
オーバーロード
演算子とかの挙動を時と場合で変える。
例えば1+2は3になるが、DateTimeオブジェクト同士を足したり引いたりしたらDateTime::Durationオブジェクトが出来たりするのは、DateTimeの中で+とか-の演算子をオーバーロードしているから。
use overload '""' => \&hoge;
としたとき、print $object;でhoge()が呼ばれる理由が分からなかったので柔道家に質問。
曰く、「文字列のコンテキストでオブジェクトが使われたら、hoge() を呼ぶのが、オーバーロード」
文字列のコンテキストじゃなくて数値で評価されたらどーなるんだろと質問。
そもそも数値で評価ってどーするんだと。
オーバーロードできるオペレータで、真偽値、文字列、数値のどれかとして評価されたときに呼ばれるやつ
それぞれ、以下。
’bool’, ’""’, ’0+’,
q{""}の意味がやっと分かった。
というわけで以下を示された。
perl -le 'use overload q{0+} => sub { 1 }, q{""} => sub {2}; my $x = bless {}; print $x; print int $x' 2 1 % perl -le 'use overload q{bool} => sub {0}; my $x = bless {}; if($x){die 1}' % perl -le 'use overload q{bool} => sub {1}; my $x = bless {}; if($x){die 1}' 1 at -e line 1.
なるほど。
printfで%dとかなら間違いなく数値
% perl -le 'use overload q{0+} => sub {1}, q{""} => sub {2}; my $x = bless {}; printf "%d", $x;' 1
確かに。
メソッド、オペレータ以外のものもオーバーロードできるのも、対象にこんなものがあるのも知らなかった。
perldoc見たら沢山あった。英語だからって避けてたらそりゃ分かりませんね。
あと
intがoverloadされてないばあいに、0+が使われる
とも言われた。意味分かってない。
変なこと編
スクリプトでは大抵こんなことを頭に書いている。
sub p ($) { print Dumper shift }
が、オーバーロードされた結果を見るときにはこいつは向いてない。
print $objectしたときに、文字列評価されたときのオーバーロード結果じゃなくて、オブジェクト自体をダンプするから。
というわけでprintを使うわけだが、めんどくさがりなのでこんなことをした。
*p = *print; p $object;
実行結果・・・
Undefined subroutine &main::print called
え?何で?また俺間違った?
*p = sub {print shift};
なら動くけどいやん。というかundefinedなのは何故だ。
全然分からなかったのでまた柔道家に助けてもらおうと。
% perl -le 'sub hoge{} *hoge = *CORE::GLOBAL::print; hoge "aa"' Undefined subroutine &CORE::GLOBAL::print called at -e line 1.
リファレンスが取得できない。
オーバーライドは可能か?
% perl -le 'BEGIN{*CORE::GLOBAL::print = sub {die}}; print "aa"' aa
あ、あれ?
組み込み関数は全てこうなのか?
% perl -le 'BEGIN{*CORE::GLOBAL::uc = sub {die}}; print uc "aa"' Died at -e line 1.
いけた。何故だ。
未だに理由不明。
ググったら、4年前に通り過ぎてる人が居た。CORE::GLOBAL::printのオーバーライド - 北海道苫小牧市出身の初老PGが書くブログ