MetaPostの変数
MetaPost の変数についてのまとめ
参考文献
- Hobby, John D. "A user’s manual for MetaPost." Computing Science Technical Report 162 (1992).
以下マニュアルと記載する.
変数名
(詳細についてはマニュアルの 7 Variables 参照)
変数について, マニュアルの記載は以下の通り. これでわかる人にはわかるらしい.
<variable> → <tag><suffix>
<suffix> → <empty>|<suffix><subscript>|<suffix><tag>
<subscript> → <number>|[<numeric expression>]
大雑把なイメージとしては,
- 変数は予約語でない文字列(tag)に添字(suffix)がついたもの
- 添字はなくてもいいし, 数字(subscript)でも文字列(tag)でもよい
- 数値変数(numeric expression)を添字にする場合は角カッコで囲む
マニュアルに記載の例:
-
alpha,==>,@&#$&,~~ -
f.top,f.bot -
x2r,x3r,x3.14r x[i]r
結構広い範囲の文字列が変数名(tag)として有効(1.). オブジェクトのプロパティのように, ピリオドによりタグを区切ることができる(fに添字としてtopもしくはbotが付いている)(2.). 添字が数字の場合はピリオドはいらない, また, 数字の中のピリオドは小数点と解釈される(3.). 数値変数を添字にする場合には角カッコで囲む(普通のプログラミング言語の配列と同じような書き方ができる)(4.).
変数宣言
変数は基本的に型を宣言してから使用する. MetaPost で使用できる型は, numeric, pair, path, transform, (rgb)color, cmykcolor, string, boolean, picture, pen の10種類.
宣言で注意する点は以下のとおり.
- 宣言なしで変数を使用すると, 型は
numericになる - 宣言の直後では値は未定義になる
-
beginfig(); ... endfig;の間では,x,y,z(およびその添字付きの変数)は宣言なしでローカル変数(beginfig,endfigのブロックの外側の影響を受けない)となり,z<suffix>=(x<suffix>,y<suffix>)である - 数字の添字(配列)を持つ変数は個別に宣言できず, 配列として宣言する
例えば, 次のような宣言はできない.
numeric q1,q2,q3;
代わりに以下のように宣言する.
numeric q[];
(角カッコを付けないと添字なしのqという変数だけが未定義になる.)
代入と方程式
(詳細についてはマニュアルの 5 Linear Equation 参照)
通常のプログラミング言語と異なり, = は代入を意味せず, 等しいこと, つまり方程式を表す. 驚くべきことに, MetaPostは線形(1次)方程式を自動的に解いてくれる. 例えば, 以下の連立方程式は,
a+b=3;2a=b+3;
以下と同じである.
a=2;b=1;
一方代入には := を使う. 例えば, インクリメントは以下のように書く.
a:=a+1;
ここで等号を使って a=a+1; としてしまうと, ! Inconsistent equation と言われエラーになる.
このように, 値を設定する, という意味では似ているが, 方程式と代入は意識して使い分ける必要がある.
a=2;b=a;a:=3;c=a; %%% 3つ目の式だけ代入
この例では前から順番に解釈することにより, 正しく値を設定できる. 仮に3つ目を a=3; としてしまうと, 1つ目の a=2; と矛盾するのでエラーになる.
スコープ
(詳細についてはマニュアルの 10 Macros 参照)
MetaPostでは begingroup; ... endgroup; で囲むことにより文をグルーピングすることができる. しかし, グルーピングするだけでは中の変数はローカルにならない.
x23=3.1;
begingroup;
y3a=1;x23:=2;
endgroup;
show x23,y3a;
これを実行すると, グルーピング内の式が反映され, 2と1という結果が表示される. グルーピング内の変数をローカルにするためには save を使用する.
x23=3.1;
begingroup;
save x,y; %%% 追加
y3a=1;x23:=2;
endgroup;
show x23,y3a;
こうすると, 3.1 と y3a(未定義) が表示され, グルーピング内で変数 x, y がローカルになっていることがわかる. 変数宣言の場合と異なり, save x,y; だけで(つまり, 角カッコなしで) x, y に添字がついた変数もすべてローカルになる.
ちなみに, 変数宣言の項で述べた, beginfig(); ... endfig; の間で, x, y, z がローカル変数になる, のは, beginfig; が begingroup;save x,y; のように展開されるためである.
逆に他の変数はローカルではないので、例えば beginfig(1) と beginfig(2) で同じ変数を使用する場合には各 beginfig で使用前に宣言を行う(宣言により未定義に戻る), もしくは, 明示的に save を使ってローカル変数にする, 等の対策をしたほうがよいと思われる.
Discussion