本連載では第一線のPerlハッカーが回替わりで執筆していきます。今回のハッカーは普段Perlでスマートフォンゲームのサーバサイドの開発をしているybrliiuこと楠田来安さんで、
本稿に記載しているコードはPerl 5.
Perlにおける動的なモジュールロード
言語の柔軟性や文化的な要因により、
本稿では、
まずは動的なモジュールロードについての説明と、
静的なモジュールロード
モジュールロードする場合、useを使うと思います。useを使った場合、useなどコンパイルフェーズで行うモジュールロードのことを静的なモジュールロードと呼びます。
静的にモジュールロードする場合は、
動的なモジュールロード
対して動的なモジュールロードは、
動的にモジュールロードする場合はロードするタイミングやモジュールを自由に決めることができるため、
動的なモジュールロードをする方法
動的なモジュールロードをする方法のうち、
require──モジュールロードをする組込み関数
Perl組込みの関数を利用して動的にモジュールロードする場合、require関数を利用します。しかし、require関数にBareword
たとえば次のコードでは、requireは@INCからFoo::Barというファイルを探してロードを試みます。
my $module_name = 'Foo::Bar';
require $module_name;require関数にモジュール名としてBareword以外の値を渡したい場合は、require関数を呼び出している箇所全体をevalで評価する必要があります。
my $module_name = 'Foo::Bar';
eval "require $module_name";しかし、evalでrequireを評価するコードはできるだけ書きたくありません。
- オーバーヘッドが発生する
- ロード時のエラーが握りつぶされる
- プログラム外部から渡された値をevalで直接評価するとインジェクション攻撃が可能になる
- 不格好なコードになる
CPANにはevalをしなくても動的にモジュールロードできるモジュールが存在していますので、requireにBareword以外の値を渡したい場合はそれらのモジュールローダを利用することが推奨されます。
Module::Load──コアモジュールのシンプルなモジュールローダ
Module::LoadはPerl 5.
use Module::Load qw( load );
load('Foo::Bar');Class::Load──クラスモジュール向けのモジュールローダ
Class::Loadは、Mooseの裏側などで利用されているクラスモジュール向けのモジュールローダです。ロードするモジュールがすでに内部パッケージやファイル名とパッケージ名が対応していないモジュールによって定義されている場合はファイルを読み込まずエラーにならないので、
次のコードもエラーにならず動作します。
package Foo::Bar;
sub do_something { warn 'Do something.' }
package main;
use Class::Load qw( load_class );
load_class('Foo::Bar');useする場合と挙動が異なる点
動的にモジュールロードした場合、useで静的にモジュールロードした場合と挙動が異なる点があるので注意が必要です。
importメソッドが呼ばれない
useした場合、importメソッドを呼び出しますが、importメソッドは呼ばれません。ですので、importメソッドの中で実行されるはずだった処理を行いたい場合は、importメソッドを呼び出す必要があります。
Module::Loadを利用している場合、autoload関数を利用するかload関数に追加の引数を与えると、importメソッドを呼び出します。
use Module::Load qw( load autoload );
load('Foo::Bar');
Foo::Bar->import();
# もしくは
autoload('Foo::Bar');括弧を省略してサブルーチンを呼び出せない
別モジュールからuseでサブルーチンをインポートした場合は、
しかし、
use Module::Load qw( load );
load 'Math::Trig', 'tan';
warn tan 0.9; #エラー同様に、
use Module::Load qw( load );
load('List::Util', 'first');
warn first { $_ == 1 } 0 .. 10; #エラーこの問題は括弧を省略せず呼び出したり、
use Module::Load qw( load );
load('Math::Trig', 'tan');
warn tan(0.9);
load('List::Util', 'first');
warn first(sub { $_ == 1 }, 0 .. 10);あるいは事前にインポートするサブルーチンの宣言を行うことで解決できます。
use Module::Load qw( load );
load('Math::Trig', 'tan');
sub tan;
warn tan 0.9;
load('List::Util', 'first');
sub first(&@);
warn first { $_ == 1 } 0 .. 10;CHECK、INITコードブロックに書かれたコードが実行されない 
CHECKブロック、INITブロックは、
<続きの
本誌最新号をチェック!
WEB+DB PRESS Vol.130
2022年8月24日発売
B5判/168ページ
定価1,628円
(本体1,480円+税10%)
ISBN978-4-297-13000-8
- 特集1
 イミュータブルデータモデルで始める
 実践データモデリング
 業務の複雑さをシンプルに表現!
- 特集2
 いまはじめるFlutter
 iOS/Android両対応アプリを開発してみよう
- 特集3
 作って学ぶWeb3
 ブロックチェーン、スマートコントラクト、NFT


