オーバーロードとか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が書くブログ

何故BEGINが要るのか

うろ覚え。本人も、多分、って言ってた。
パース>中間言語に>実行 の流れで、パースの際に組み込み関数を上書きする必要があるから?


しまいにはperlのソース嫁って流れに。
ああもうグダグダすぎるけど終わり。
いやーperl全然わからねーなー。むずし。