openプラグマの落とし穴
openプラグマの挙動が異様だ。
以下のようなライブラリHoge.pmがあったとする。ライブラリファイルのエンコーディングはShift_JISとする。
package Hoge; sub hoge{ use Data::Dumper; my $hoge = "ほげ!"; printf "is_utf8: %d\n", utf8::is_utf8($hoge); print Dumper $hoge; } 1;
そしてこれを以下のようなスクリプトhoge.plから呼び出すとする。
#!perl -w use strict; use open ':encoding(Shift_JIS)'; use Hoge; Hoge::hoge(); __END__
このコードは何が出力するだろうか。何を出力するべきだろうか。
実際の出力は以下のようになる。
is_utf8: 1 $VAR1 = "\x{307b}\x{3052}\x{ff01}";
\x{....}となっているのはUTF-8フラグが立っているためである。つまり,ライブラリファイルは呼び出し元のopenプラグマの影響を受ける。これはopenプラグマが暗黙のPerlIOのopen()にも影響を及ぼし,さらにPerlインタプリタがライブラリファイルを読み込む際にPerlIOのopen()を介するせいだが,それでもライブラリファイルがそのまま影響を受けてしまうのはちょっといただけない。
なお,スクリプトファイルで"use open ':utf8';"とすると,Hoge.pmの"ほげ!"というリテラルはUTF-8ではないため,今度は"Malformed UTF-8 character"という警告とともにリテラルデータが壊れるということになる。ライブラリファイルで"use encoding 'Shift_JIS';"などとしても状況は変わらない。
もともとopenプラグマは使いこなすのが難しいので,「使わない」というのが正解かもしれない。