メメメモモ

プログラミング、筋トレ、ゲーム、etc

コンパイルフェイズとインタプリタフェイズで自動実行される部分について

BEGINブロック、CHECKブロック、INITブロック、ENDブロック

Perlプログラムが実行されるまでの流れは下記のようになります。

f:id:memememomo:20100420194121p:image


この流れの中で自動実行されるブロックがあります。
実行されるブロックとその実行タイミングは以下のようなものです。

  • INITブロック
    • コンパイルフェイズで実行されるブロック
  • CHECKブロック
    • コンパイルフェイズが終了した時に実行されるブロック
  • INITブロック
  • ENDブロック


これが本当かどうかを、確認用のプログラムで確かめてみます。

use strict;
use warnings;

print "start main running here\n";
die "main now dying here\n";
die "XXX: not reached\n";

END      { print "END: done running\n" }
CHECK { print  "CHECK: done compiling\n" }
INIT      { print "INIT: started running\n" }
BEGIN   { print "BEGIN: still compiling\n" }


まずこのプログラムを「perl -c」コマンドに読み込ませてみます。
このコマンドは、コンパイルだけ行ない実行はしません。
ということなので、コンパイルフェイズで実行されるものだけが実行されることになります。
表示結果は下記のようになりました。

BEGIN: still compiling
CHECK: done compiling


BEGINブロックとCHECKブロックのみが実行されていますね。


次に「perl」コマンドに読み込ませます。
今度はプログラムが実行されます。
表示結果は下記のようになりました。

BEGIN: still compiling
CHECK: done compiling
INIT: started running
start main running here
main now dying here
END: done running


コンパイルフェイズで実行されるBEGINブロック,CHECKブロックが実行され、
インタプリタフェイズ開始で実行されるINITブロックが実行され、
print関数、die関数が実行され、
プログラムが終了してENDブロックが実行されました。

requireとuseの違いについて

モジュール読み込み関数として「require」と「use」があります。
両者の違いはどこにあるかというと、読み込むタイミングにあります。
require関数は、実行処理の流れで呼び出されるまで、モジュールを読み込みません。
use関数は、コンパイルフェイズでモジュールを読み込みます。
例えば「use MyTest」は、下記のプログラムと同等の意味を持っています。

BEGIN {
   require MyTest;
   MyText::import;
}


試しにMyTest.pmを作成して読み込んでみます。

package MyTest;
use strict;
use warnings;

sub import { print "Imported\n" }

1;


このモジュールをuseで読み込んでいるプログラムを「perl -c」で実行すると「Imported」と表示されます。