open local(*FILEHANDLE)とB::Deparse

IO::scalarでIOのキャプチャは一行でできる気がしたのでやってみる。

{
  open local(*STDIN), '<', \"Hello, world!\n";
  print <STDIN>; # => Hello, world!
}
print scalar <STDIN>;

これでうまくいった。

しかし,local()の括弧をはずすとPrecedence problemという警告が出る。perldoc perldiagによれば,優先順位の問題で,"open FOO || die"という古いイディオムに対して警告しているらしい。"open local *STDIN"はPerlのParserには"open A * B"と見えるのかもしれない。

そこでDeparseしてみると:

$ perl -MO=Deparse -e 'open local *STDIN'
Precedence problem: open local should be open(local) at -e line 1.
open STDIN;
-e syntax OK
$ perl -MO=Deparse -e 'open local(*STDIN), "<", "/dev/null"'
open STDIN, '<', '/dev/null';
-e syntax OK

local()が消えた。
他の関数で同様のDeparseをしてもlocal()が消えたりはしないし,最初に示したコードではスコープの外のでは普通にSTDINからの入力を待っているので動いてはいる。これはどうもB::Deparseのバグらしい。