NeverBlog::Likk::Unexistable;

見なかったことにして下さい

普段は宣言できないサブルーチン名の作り方

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
&::&