Go to the first, previous, next, last section, table of contents.


条件つきの書替え規則

書替え規則は条件つきにする事もできて、 `old := new :: cond' 書式で書きます。 (旧書式は `[old, new, cond]' でした。) 規則内に cond 部分が存在すると、 それは規則を受付ける前に満たさねばならない追加条件です。 いったん old がターゲット式にマッチすると、 cond は(全てのメタ変数を対応する値に置換えられた状態で) a s (calc-simplify) によって evaluate され簡単化されます。 もし結果が非ゼロの数値か非ゼロが確定している(宣言 参照 )なら、 その規則が受入れられます。 結果がゼロか、あるいは非ゼロが確定していないシンボル形式の場合、 その規則は却下されます。 多様なテスト結果に応じて 1 か 0 を返す関数群については、 論理演算 参照 。

例えば、式 `n > 0'n が正か正でない数に置き換われば (または n が正か正でないとして宣言されていれば)、 それぞれ 1 か 0 に簡単化します。 従って、規則 `f(x,y) := g(y+x,x) :: x+y > 0'`f(0, 4)' には適用されますが、 `f(-3, 2)'`f(12, a+1)' には作用しません (a が特に宣言されてない場合)。 `f(-3, 2)' の場合、条件が満たされていないことが明らかです。 `f(12, a+1)' の場合は、条件の真偽が不明なだけですが、 それだけで規則が却下されるには充分です。

Calc は宣言を手がかりにターゲット式中の変数を推論するのですが、 宣言はメタ変数には作用しません。 たとえ変数`a'が実数やスカラとして宣言されていても、 規則 `f(a) := g(a+1)' は メタ変数 `a' が複素数だろうがベクトルだろうが式だろうが、 どんな値でもマッチします。 メタ変数 `a' を実数に対してのみマッチさせたい場合は、 `f(a) := g(a+1) :: real(a)' としてください。 実数と実数値をとっていることが確かな式にマッチさせたい場合は、 条件として `dreal(a)' を使ってください。

`::' 演算子は condition 関数の短縮形であり、 `old := new :: cond' は、 式 `condition(assign(old, new), cond)' と同等です。

複数の条件があるときは、 `... :: c1 :: c2 :: c3'`... :: c1 && c2 && c3' とします。 両者は完全に同等です。

パターン内に条件を埋込むことも可能で、 `f(x :: x>0, y) := g(y+x, x)' とします。 これは注釈的で便利ですが、 規則内で条件が出現する場所とその条件がテストされるタイミングは無関係です。 書替え規則のコンパイラは、 各条件をテストする最適なタイミングを自動的に判断します。

ある特定の条件は、 書替え規則エンジンによって特別に扱われ、 非常に効率的にテストされます。 特定の条件とは、x を任意のメタ変数として `integer(x)', `real(x)', `constant(x)', `negative(x)', `x >= y' など6種類の関係演算子(y は定数か他のメタ変数), `x % a = b' (ab は定数)です。 `x >= y+1' とか `dreal(x)' といった他の条件では、 チェックのためにあらゆる評価・簡単化エンジンを総動員しなければならないので 効率が下がります。

`::' の面白い性質は、 引数のどれも Calc のデフォルト簡単化に処理されないことです。 条件の多くは式表現であり、初期には安全に evaluate できないので、 これは重要です。 例えば typeof 関数は普通ならシンボリックなまま残ることは無く、 `typeof(a)' と入力するとスタックには数字の100(変数を示すコード)が 置かれます。 しかし条件 `... :: typeof(a) = 6' をスタックに置くと、 `::'typeof が実際の書替え時まで evaluate されないように 守るので、シンボリックなまま残されます。

`::' はその左辺も守るので、 初期に evaluate されたくない規則にダミー条件を付けて守ることができます。 例えばスタックに `a(f,x) := apply(f, [x])' と置くと、 即座に evaluate されて `a(f,x) := f(x)' になってしまい、 右辺の f のメタ変数的性質が失われてしまいます。 しかし `a(f,x) := apply(f, [x]) :: 1' とすれば、 シンボリックなまま残ります。 しかも当然ながら、条件 `1' は常に真(非ゼロ)なので、 規則の動作に影響はありません。 (書替え規則コンパイラは、 マッチング速度にすら影響しないことを保証します。)


Go to the first, previous, next, last section, table of contents.     利用度数