perl-5.10のperl機能を排除し、Mojoliciousをperl-5.8.7で動くよう改造したmojo-legacyのv3.54
こんにちは。須釜です。
つい先日、mojo-legacyの最新版をgithubにアップしたので、今日はその作業内容を通じて、mojo-legacyをご紹介します。
mojo-legacyはMojoliciousをperl-5.8.7環境でも動くように改造したものです。どんな改造か一言で言うと、主にperl-5.10のperlの機能を排除しています。
もう少し具体的に言うと、主に下記のようなことをしており、ほとんどが単調な手作業です。perl-5.10以降では正規表現をはじめ、多くの変更点があるようですが、幸い、Mojoliciousでは下記以外には非互換な機能は使っていないようです。
- defined-or演算子を書き換え
- スマートマッチを書き換え
- stateをourに書き換え
- sayをMojo::Baseで提供
- reモジュールをMojoLegacy::reに差し替え
- 最新のGetopt::Longをバンドル(new)
- その他の小細工
defined-orはperl-5.10から導入された演算子ですので、それ以前のperlでは使えません。
my $value = $self->value // '';
perl-5.8系で等価なコードは下記のようになります。
my $value = defined $self->value ? $self->value : '';
//=も
$self->{raw_size} += length($chunk //= '');
同様に、下記のように書き換え可能です。
$self->{raw_size} += length($chunk = defined $chunk ? $chunk : '');
下記のようなコードは書き換えづらいですが
$self->{buffer} .= shift // '';
doブロックで一時変数を使って凌いでいます。
$self->{buffer} .= do {my $buffer = shift; defined $buffer ? $buffer : ''};
次にスマートマッチです。最近のMojoliciousは、将来、スマートマッチの仕様が変更されるのに配慮して、あまり使わない方針にしたようですが、まだ下記のようなコードが残ってます。
return $self->new(grep { $_ ~~ $cb } @$self);
これは、たぶん下記のようなコードが等価になると思います。長くなってイヤなのですが、もっといい書き方があるでしょうか。
if ((ref $cb) eq 'CODE') { return $self->new(grep { $cb->($_) } @$self); } else { return $self->new(grep { $_ =~ $cb } @$self); }
state変数は
sub singleton { state $loop ||= shift->SUPER::new }
ourで代用しています。
our $singleton_loop; sub singleton { $singleton_loop ||= shift->SUPER::new }
実際の変更点は、私の作業用のリポジトリのdiffを見て頂くと分かります。
mojo-legacyのv3.54からは、テストのためにTest::Moreをアップグレードする必要があります。また、morboを使用するためにはSocketもアップグレードする必要がありそうです。非コアモジュールに依存してしまいますが、これは開発環境のお話なので、出来上がったアプリをperl-5.8.7にデプロイするだけであれば、アップグレードの必要はありません。
cpanm Test::More cpanm Socket
なお、今回からGetopt::Longもバージョン依存になってしまったのですが、こちらは本番環境でも使われるため、バンドルしました。
レガシーな環境に何かを移植する際の参考に(?)なれば幸いです。
ご意見・参考などお待ちしています!