💨

MetaPostの変数

2023/09/27に公開

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)を添字にする場合は角カッコで囲む

マニュアルに記載の例:

  1. alpha, ==>, @&#$&, ~~
  2. f.top, f.bot
  3. x2r, x3r, x3.14r
  4. 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