NAME
macro::JA - マクロプロセッサ
SYNOPSIS
use macro add => sub{ $_[0] + $_[1] };
say add(1, 3); # it's replaced into 'say do{ (1) + (3) };'
use macro sum => sub{ my $sum=0; for my $v(@_){ $sum+=$v }; $sum };
say sum(1, 2, 3); # => 6
use macro my_if => sub{ $_[0] ? $_[1] : $_[2] };
my_if( 0, print('true'), print('false') ); # only 'false' is printed
# or compile only
$ perl -c Module.pm # makes Module.pmc
DESCRIPTION
macro
プラグマはCのプリプロセッサに似たマクロを提供する。 このマクロを呼び出すと,マクロのコードをマクロの呼び出し元に展開され, 関数呼び出しを伴わずにコードが実行される。このマクロ展開はコンパイル時に ソースフィルタリングメカニズムを通して行われる。また,ソースコードの解析にはPPI
を用いている。
このマクロの呼び出しは非常に高速だが,Cプリプロセッサのマクロと同じ制限もある。たとえば, マクロの中でreturn()
を呼ぶと期待通りには動作しない。マクロの定義は関数 の宣言のようにに見えるが,実際には関数のように動作するわけではない。
マクロが展開される様子は,環境変数PERL_MACRO_DEBUG
に2
を指定することに よって知ることができる。
なお,マクロはレキシカルスコープである。
MACRO CALL
マクロの呼び出しは関数の呼び出しに似ており,マクロの名前の後に括弧で括った引数 リストを付けて呼び出す。引数リストの括弧を省略することはできない。
&
を付けた関数呼び出しやアロー演算子によるメソッド呼び出しははマクロ呼び出しとは見做されないが, 間接オブジェクト構文によるメソッド呼び出しはマクロ呼び出しと区別がつかず,誤って展開される可能性がある。
なお,PPIの制限により,ダブルクォートの中の式展開や,s/regex/expr/e
の式展開は パースされず,その結果マクロの展開も行われない。
MACRO ARGUMENTS
マクロの展開はCプリプロセッサに似ている。
マクロの定義において,@_
や$_[0]
によってマクロの実引数を参照できる。 たとえば,$_[0]
はマクロ呼び出しの第一引数に置き換えられる。 これは関数の引数に似ているが,実体はまったく異なり,@_
のようなトークンを 実際の値に置き換えている。このとき,$_[0]
というのはこれで単一のトークン として扱われ,添字として使えるのは単純な数値だけである。たとえば,$_[$i]
は マクロの引数としては扱われず,マクロを呼び出した関数の引数を参照する。
Cプリプロセッサのマクロと同じく,$_[0]
などのプレースホルダを参照しなければ 実引数は評価されず,プレースホルダを複数回参照すれば,実引数は複数回評価される。
また,Cプリプロセッサと違い,プレースホルダによって置き換えられる実引数 は常に単項プラス演算子が前に置かれ,括弧で囲まれる(つまり+(expr)
となる)。 これは以下のようなマクロ定義を正しくおこなうためである。
use macro say => sub{ print @_, "\n" };
say('Hello, world!');
この引数のプレースホルダ@_
は以下のように置き換えられる。
print +('Hello, world!'), "\n";
引数の扱いでは実行時のコンテキストが考慮されず,Cプリプロセッサのように 扱う点でも関数の呼び出しとは異なる。
use macro my_each => sub{ foreach ($_[0]) { $_[1] } };
my_each( (@a, @b, @c), say($_) );
これは以下のように置き換えられる。
foreach ( +(@a, @b, @c) ){ +(say($_)) }
また,ダブルクォートの中のプレースホルダ(@_)は置き換えられない。 以下のマクロの@_
は展開されず,マクロの呼び出し元の引数が参照される。
use macro println => sub{ print "@_\n" }; # おそらく予想外の挙動
マクロの中ではpackage
やプラグマの効果はなく,常に呼び出し元の環境の下で実行される。
BACKEND MODULE
このモジュールのバックエンドとして,macro::filter
とmacro::compiler
が 存在する。デフォルトのバックエンドはmacro::compiler
だが, 環境変数PERL_MACRO_DEBUG
に1
を設定することで,macro::filter
の 使用を強制できる。
macro::filter
はソースフィルタとして働くため,スクリプトをロードする度に マクロ展開を行うが,余計なファイルを作成しない。
macro::compiler
はModule::Compile
に似たスクリプトコンパイラとして動作し, ファイルの末尾にc
が付加されたスクリプトファイルを生成する (たとえば,Foo.pm
からはFoo.pmc
が作られる)。Perlのuse Foo
ディレクティブはFoo.pmc
が存在すればFoo.pmc
を読み込むので,コンパイル済み のスクリプトファイルは常に高速に動作する。また,コンパイルされたファイルは, オリジナルファイルの修正時間(mtime)に基づくチェックを行い,自動的に再コンパイル を行う。 オリジナルファイルはコンパイル済みファイルと同じディレクトリにあると仮定され, オリジナルファイルが見つからない場合はいかなるチェックも行われない。
perlを-cスイッチと共に使うことで,macro::compiler
によるコンパイルのみを行う こともできる。
バックエンドモジュールをロード後に変更することはできないが,バックエンド モジュールを直接use
することはできる。
実行時の速度はどちらのバックエンドも変わらない。
PMC Support
macro
を使うモジュールは,Module::Install::PMC
を使ってインストールの前にモジュールをコンパイルすることができる。 そのためには,Makefile.PL
に以下のように書けばよい。
use inc::Module::Install;
...
build_requires 'macro';
pmc_support;
...
Module::CompileとModule::Install::PMCも参照せよ。
METHODS
macro->backend()
バックエンドモジュールの名前を返す。 これはmacro::filter
かmacro::compiler
である。
macro::compiler
バックエンドによってコンパイルされたファイルは,macro.pm
をロードしないため,<macro-
backend()>>を呼び出すことができないので注意せよ。
macro->new()
マクロプロセッサのインスタンス$macro
を返す。
new()
, defmacro()
, process()
はバックエンドモジュールを 実装するためのメソッドである。
$macro->defmacro(name => sub{ ... })
マクロプロセッサ$macroにマクロを定義する。
$macro->process($source)
Perlソースコード$sourceを受け取り,マクロ展開を行ったソースコードを返す。
CONFIGURATION AND ENVIRONMENT
PERL_MACRO_DEBUG=value
デバッグモードを設定する。
この値を指定しないか0であれば,macro::compiler
がバックエンドとして使われる。
この値が1より大きければ,macro::filter
がバックエンドとして使われる。
この値が2より大きければ,マクロの展開の様子がSTDERR
に出力される。
INSTALL
To install this module, run the following commands:
perl Makefile.PL
make
make test
make install
DEPENDENCIES
Perl 5.8.1 or later.
PPI
- Perl parser.Filter::Util::Call
- Source filter utility.
BUGS AND LIMITATIONS
No bugs have been reported.
Please report any bugs or feature requests to bug-macro@rt.cpan.org/
, or through the web interface at http://rt.cpan.org/.
SEE ALSO
macro::filter - macro.pm source filter backend.
macro::compiler - macro.pm compiler backend.
AUTHOR
Goro Fuji <gfuji(at)cpan.org>.
LICENSE AND COPYRIGHT
Copyright (c) 2008-2009, Goro Fuji <gfuji(at)cpan.org>. Some rights reserved.
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.