普段は宣言できないサブルーチン名の作り方
perl のサブルーチン名は数字で始まったり、アンダスコア以外の記号を使ったサブルーチンは宣言できない。
use strict; use warnings; sub 0 { print '0' } &0;
実行すると下記の様に怒られる。
$ perl ./hoge.pl Illegal declaration of subroutine main::a at ./hoge.pl line 4.
しかし下記のようにパッケージのシンボルテーブルをcoderef上書きすると実行できる。
use strict; use warnings; { no strict 'refs'; *{__PACKAGE__ . '::0';} = sub { print 0; }; &0; use strict; }
$ perl ./hoge.pl 0
もう何でもありである。というムダ知識を得たんだ。
use strict; use warnings; { no strict 'refs'; *{__PACKAGE__ . '::1-1'} = sub { say "1-1" }; *{__PACKAGE__ . '::&'} = sub { say "&" }; *{__PACKAGE__ . ':: '} = sub { say " " }; &{"1-1"}; &{&}; &{' '}; use strict; }
追記:という話をperl界隈の人に言ったら、「それ去年のYAPCで…」と言われたので帰ろうと思う。
さらに追記:クラス定義も出来るという話を聞いた。そりゃそうだ。
package main; use strict; use warnings; { no strict 'refs'; *{'&::&'} = sub { shift; say '&::&'}; *{'&::new'} = sub { return bless {}, '&' }; my $method = '&'; "&::new"->()->$method; #なんかもうちょっと良い呼び出し方ありそう。 use strict; }
$ perl ./hoge.pl &::&