読者です 読者をやめる 読者になる 読者になる

M4の定義混在モデルにより可能なこと

M4入門( http://metanest.jp/m4intro/ )のサプリメンタリーのような内容です。
M4は基本設計がシンプルイズベスト、という感じのところがあり(ストレイチーさんによるGPMはたった250語で実装されていたそうです)、いろいろと「現代風に作り直したら?」と考えたくなるところがあります。
そのうちの一つとして、定義は定義だけをまとめたファイルから読み、マクロ処理の対象中では定義を行わないようにする、というものが考えられます。
M4でも、運用でそのように制限することはできますが、定義が混在することで可能になっているテクニックが使えないということになります。具体例を紹介します。
一部のプログラミング言語には、関数名や手続き名に代入することで、関数やプロシージャからの返り値を指定する、という文法があります。関数名や手続き名を変更すると、返り値を指定しているところも書き換える必要がありますから、DRY (Don't Repeat Yourself) 的ではありません。これをマクロを使って解決したい、とします。
M4ファイルでは次のようになります。

define(`BEGIN_FUNC', `define(`func_name', `$1')func $1() {')dnl
define(`RETURN', `func_name := $1')dnl
define(`END_FUNC', `}')dnl
BEGIN_FUNC(`sample')
	hoge
	RETURN(`42')
END_FUNC()

これをM4で処理すると、次のようになります。

func sample() {
	hoge
	sample := 42
}

(func_nameという名前がぶつかるとまずい、とか、END_FUNCでundefしたほうが良い、とか色々あるんですが、そのへんは気にしないことにしてください)
定義が混在できることで、こういったことが簡単にできますが、定義を分離したうえでこれを実現するとなると、変数とか何か別の仕掛けを作り込まないといけなくなります。