シンボルテーブルとグロブ(2)

おさらい

  • シンボルテーブルは普通のPerlハッシュで実装されています。
  • Perlhogeという名前の変数には$hoge, @hoge, %hoge, &hoge, ファイルハンドルのhoge, ディレクトリハンドルのhogeなどがあります。
  • これらのhogeは物理的にはバラバラの場所に離れています。((メモリのブロックが違うとか、そんな感じの意味です。

))

  • ただし、それぞれへのリファレンスは同じハッシュ内に含まれています。
  • そのハッシュはグロブと呼ばれており、それへのリファレンスはアスタリスクからはじまっています。
  • このようにPerlでは変数ルックアップに2つの段階を経て処理しています。
    • 最初の段階で、適切なグログをシンボルテーブルから発見します。名前ルックアップ。
    • 次の段階ではグロブから求めるべきリファレンスを見つけます。リファレンスルックアップ。

※話がずいぶんとショートカットしているかもしれませんが、それは後日調整します。

グロブ割り当てによるエイリアス

グロブの仕組みを学ぶと、次のような処理が理解できます。

package Foo;
use strict;
use warnings;

sub test_method { 'hoge' }

sub import {
    no strict 'refs';
    *{ caller(). "::test_method"} = *test_method;
}

1;
importとcaller

importは何をするのでしょうか?perldocを見てみましょう。例では

%perldoc -f import

Pod::PerldocJpを導入している場合は次のコマンドが便利です。

% perldocjp -Jf import

「"use" 関数はパッケージを使う時に "import" メソッドを呼び出します。」という記述があります。

つまり、use Foo::Bar;と書いたパッケージはimport内の処理を自動的に実行するようにできます。

次にcallerです。同様に調べましょう。

%perldoc -f caller

Pod::PerldocJpを導入している場合は次のコマンドが便利です。

% perldocjp -Jf caller

解説を要約すると、呼び出した名前空間を知ることができる、という事です。

no strict 'refs' に関してはまた次の機会に説明したいと思います。*1興味がある方は perldoc strict;を実行して下さい。

次のコードをご覧ください。このパッケージにはtest_methodというメソッドが生えているという事が分かっている方はもうシンボルテーブルとグロブに関して理解していると思います。

#!/usr/bin/perl
use strict;
use warnigs;
use Foo;

test_method();

Package Foo;

sub test_method { print 'hoge' }

sub import {
    no strict 'refs';
    *{ caller(). "::test_method"} = *test_method;
}

1;

補足説明

今回紹介したコードを見ただけでは混乱する人しかいない*2と思いますので補足したいと思います。

次のようなコードをご覧ください

package main;
use strict;
use warnings;
use lib 'lib';
use Foo;

test_method(); # hoge

warn *main::test_method; # *Foo::test_method

use Foo::Barには次の効用があります。

  • Foo::Barにあるimportメソッドが実行されます。
  • importメソッドではcallerが実行されます。
  • callerが実行されると、呼び出し元の名前空間を取得します。
  • この場合はmainです。連結して *main::test_methodに変化します。
  • これはグロブです。

*1:私がよくわかってないので説明できないという。シンボリックリファレンスは使い方を知るものだけが使うべき、という理由らしいです。

*2:分かっている人はもうこんな記事読んでないことでしょう