モーグルとカバとパウダーの日記

モーグルやカバ(EXカービング)山スキー(BC)などがメインの日記でした。今は仕事のコンピュータ系のネタが主になっています。以前はスパム対策関連が多かったのですが最近はディープラーニング関連が多めです。

レガシーなperlスクリプトをuse strict対応するのに便利なExporterの使い方

仕事でレガシーなperlスクリプトのメンテナンスをすることになり、use strict対応がたいへん…(もちろんそれだけじゃないけど)となりました。

conf.plみたいに設定ファイルが別ファイルとしてあって、それもuse strictとConf.pmとパッケージ化した場合、そこで設定されている大域変数を全て Conf::GLOBAL_VAR みたいに Conf:: のようなパッケージ名を付けて回る必要があります。
大域変数使いまくりなレガシーな設計になってたりすると、この名前変更してまわるだけでも結構神経使うし読みづらくなります。


そしたら僕のperl師匠の @hkoba さんに Exporter というmoduleを教えてもらいました。


Exporter - perldoc.perl.org


これは、他のパッケージにある関数や大域変数を、パッケージ名を付けずに呼び出せるというものです。


これを設定ファイルで宣言される大域変数に使ってやります。

例えば、Conf.pm の中で

package Conf;
use strict;
use Exporter 'import';
our EXPORT = qw( $FOO_VAL bar_function );

our $FOO_VAL = 'hoge';
sub bar_function {
…

とか書いてあれば

use strict;
use Conf;

print $FOO_VAL;
bar_function();

というように、$Conf::FOO_VAL みたいにパッケージ名を付けなくても参照できるわけです。


大域変数の設定を別ファイルにして出していたり、汎用関数を別ファイルにしている場合は結構多いと思いますが、そんな時にいちいちパッケージ名付けて回るのは大変ですが、これ使えばexport側で宣言するだけで不要になります。


またパッケージ名を付けて大域変数を呼び出すやり方でtypoした場合、例えば

use strict;
use Conf;

print $Conf::FOOO_VAL; # strictでの検査に掛からない
print $FOOO_VAL;       # strictでの検査に掛かる

の上の例のようにパッケージ名付きの名前「$Conf::FOOO_VAL」ではuse strictの検査に掛からないのです。
しかし、Expoterで宣言したものだけが使えるようにする場合、ちゃんとstrictでの検査に掛けることができます。
この利点はとても大きいと思います。


実はExporterのドキュメントには

There's one more item to add to this list. Do not export variable names. Just because Exporter lets you do that, it does not mean you should.

    @EXPORT_OK = qw( $svar @avar %hvar ); # DON'T!

と、大域変数に対してexportするのはやめれ、と書いてあります。
しかし、元々大域変数使いまくりな設計になっている場合には仕方ないよね、ということで大域変数にも使いました。
ダメと書いてあるけどちゃんと使えます。


このような「設定ファイルで使う大域変数に対しExporter使って表記を簡潔にする」という使い方は、本来のExporterの使い方ではありません。(なので@ISAの設定もしなくてよい)
ですがこういう使い方もありますよ、ということでした。