evalとpackage。
wakaponさんのよく☆ある☆ふつーの備忘帳:packageの件について
http://pub.ne.jp/wakapon/?entry_id=1981011
こちらの記事の最後にあったいろいろなおまけ、
自分でもいくつか考えてやってみたのでまとめ。
eval 'package HOGE; print __PACKAGE__; $num = 123;'; our $num = 1234; # こいつはmainに属する eval 'print $HOGE::num';
元記事のおまけ5の派生。
出力は
HOGE123
となった。
packageの効果範囲はmyと似ていて、「宣言したスコープから抜ける」まで。
evalに与えた文字列は「ひとつのブロックの中」として扱われる。
なので、1行目の「$num = 123;」はHOGE空間で実行されることになり、
$HOGE::numに値が存在することとなった。
これは「同じeval中で代入したから」ではなく「package宣言と同じスコープで代入したから」である点が重要。
つまり、
eval '{ package HOGE; print __PACKAGE__; } $num = 123;'; our $num = 1234; # こいつはmainに属する eval 'print $HOGE::num'; # 何も出力されない
ということになる。
package宣言を一つ深いスコープに持っていった。
すると「$num = 123;」はHOGE空間を抜けた後、main空間で実行されることになる。
eval '{ package HOGE; print __PACKAGE__; } $num = 123;'; print $num; # 123
ってこと。
あとevalとは関係ないけど、package宣言は同じ空間を複数回宣言することもできる。
package HOGE; $num = 1; package main; print $HOGE::num; # 1 print $HOGE::foo; # undefined package HOGE; $foo = 2; package main; print $HOGE::num; # 1 print $HOGE::foo; # 2
要するに「HOGEって部屋に出たり入ったり」してるってこと。
2回目以降の宣言で上書きされるわけではなく、追記。