@menu
* Introduction to Rules and Patterns::  
* Functions and Variables for Rules and Patterns::  
@end menu

@c -----------------------------------------------------------------------------
@node Introduction to Rules and Patterns, Functions and Variables for Rules and Patterns, Rules and Patterns, Rules and Patterns
@section Introduction to Rules and Patterns
@c -----------------------------------------------------------------------------

この節ではユーザー定義のパターンマッチングと整理ルールを記述します。
幾分違ったパターンマッチング体系を実装した２つの関数グループがあります。
１つのグループは、@code{tellsimp}, @code{tellsimpafter}, @code{defmatch},
@code{defrule}, @code{apply1}, @code{applyb1}, @code{apply2}です。
他のグループは、@code{let}, @code{letsimp}です。
どちらの体系も、
@code{matchdeclare}が宣言したパターン変数を使ってパターンを定義します。

@code{tellsimp}と@code{tellsimpafter}が定義するパターンマッチングルールは、
Maximaの整理器によって自動的に適用されます。
@code{defmatch}, @code{defrule}, @code{let}によって定義されたルールは、
明示的に関数をコールすることで適用されます。

更に、@code{tellrat}が多項式に適用するルール用メカニズムと、
@code{affine}パッケージの可換/非可換代数用メカニズムがあります。

@opencatbox
@category{Simplification} @category{Rules and patterns}
@closecatbox

@c end concepts Rules and Patterns

@c -----------------------------------------------------------------------------
@node Functions and Variables for Rules and Patterns,  , Introduction to Rules and Patterns, Rules and Patterns
@section Functions and Variables for Rules and Patterns
@c -----------------------------------------------------------------------------

@c NEEDS CLARIFICATION AND EXAMPLES

@c -----------------------------------------------------------------------------
@anchor{apply1}
@deffn {関数} apply1 (@var{expr}, @var{rule_1}, ..., @var{rule_n})

@var{rule_1}を @var{expr}に、失敗するまで繰り返し適用して、
それから同じルールを @var{expr}の部分式すべてに左から右へ、
部分式すべてで @var{rule_1}が失敗するまで繰り返し適用します。

この方法で @var{expr}を変換した結果を @var{expr_2}と呼ぶことにします。
次に、 @var{rule_2}を @var{expr_2}の最上部から始めて同じ方法で適用します。
@var{rule_n}が最後の部分式上で失敗する時、結果が返されます。

@code{maxapplydepth}は、
@code{apply1}と @code{apply2}が処理する最も深い部分式の深さです。

@code{applyb1}, @code{apply2}, @code{let}も参照してください。

@opencatbox
@category{Rules and patterns}
@closecatbox
@end deffn

@c NEEDS CLARIFICATION AND EXAMPLES

@c -----------------------------------------------------------------------------
@anchor{apply2}
@deffn {関数} apply2 (@var{expr}, @var{rule_1}, ..., @var{rule_n})

もし@var{rule_1}が与えられた部分式上で失敗したら、
@var{rule_2}が繰り返し適用されます、などなど。
すべてのルールが与えられた部分式上で失敗した時だけ、
ルールの全組が次の部分式に繰り返し適用されます。
もしルールの１つが成功したら、
同じ部分式が最初のルールから再処理されます。

@code{maxapplydepth}は、
@code{apply1}と@code{apply2}が処理する最も深い部分式の深さです。

@code{apply1}と@code{let}も参照してください。

@opencatbox
@category{Rules and patterns}
@closecatbox
@end deffn

@c NEEDS CLARIFICATION AND EXAMPLES

@c -----------------------------------------------------------------------------
@anchor{applyb1}
@deffn {関数} applyb1 (@var{expr}, @var{rule_1}, ..., @var{rule_n})

失敗するまで、繰り返し
@var{expr}の最も深い部分式に
@var{rule_1}を適用し、
その後、
@var{rule_1}がトップレベルの式で失敗するまで、
同じルールを１つ高いレベル(すなわち、より大きな部分式)に適用します。
その後、@var{rule_2}が@var{rule_1}の結果に
同様に適用されます。
@var{rule_n}がトップレベルの式に適用された後、結果が返されます。

@code{applyb1}は
@code{apply1}に似ていますが、
トップダウンからの代わりにボトムアップから働きます。

@code{maxapplyheight}は
@code{applyb1}が、あきらめる前に届く
最大の高さです

@code{apply1}, @code{apply2}, @code{let}も参照してください。

@opencatbox
@category{Rules and patterns}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{current_let_rule_package}
@defvr {オプション変数} current_let_rule_package
デフォルト値: @code{default_let_rule_package}

@code{current_let_rule_package}は、
もし他のルールパッケージが指定されないなら、
(@code{letsimp}など)@code{let}パッケージの関数で使われる
ルールパッケージの名前です。
 @c NEED TO GIVE AN EXPLICIT LIST HERE (NOT "ETC")
この変数は、@code{let}コマンドを介して定義された任意の規格パッケージの名前を
割り当てられます。

もし
@code{letsimp (expr, rule_pkg_name)}のようなコールがされたら、
ルールパッケージ@code{rule_pkg_name}は
その関数コールだけのために使われ、
@code{current_let_rule_package}の値は変わりません。

@opencatbox
@category{Rules and patterns}
@closecatbox
@end defvr

@c -----------------------------------------------------------------------------
@anchor{default_let_rule_package}
@defvr {オプション変数} default_let_rule_package
@c DEFAULT BINDING OF default_let_rule_package IS default_let_rule_package (BOUND TO ITSELF)
デフォルト値: @code{default_let_rule_package}

@c THIS IS SORT OF CONFUSING. PROBABLY NEED TO GIVE MORE DETAIL HERE
@code{default_let_rule_package}は、
@code{let}でユーザーによって、
また、@code{current_let_rule_package}の値を変更することによって、
陽に設定されない時使われる
ルールルールの名前です。

@opencatbox
@category{Rules and patterns}
@closecatbox
@end defvr

@c -----------------------------------------------------------------------------
@anchor{defmatch}
@deffn  {関数} defmatch (@var{progname}, @var{pattern}, @var{x_1}, @dots{}, @var{x_n})
@deffnx {関数} defmatch (@var{progname}, @var{pattern})

@var{pattern}にマッチするか見るために @var{expr}をテストする
関数@code{@var{progname}(@var{expr}, @var{x_1}, ..., @var{x_n})}
を定義します。

@var{pattern}は、
 (引数として与えられているなら)
パターン引数 @var{x_1}, ..., @var{x_n}を含む式です。
パターン引数は @code{defmatch}の引数として明示的に与えます。
一方、@code{matchdeclare}関数がパターン変数を宣言します。
@code{matchdeclare}のパターン変数か @code{defmatch}のパターン引数として宣言されていない
任意の変数はそれ自身とのみマッチします。

生成関数@var{progname}の最初の引数はパターンに対してマッチされる式であり、
他の引数は、パターンの中のダミー変数@var{x_1}, ..., @var{x_n}に対応する
実際の引数です。

もしマッチが成功したなら、
@var{progname}は、
左辺がパターン引数やパターン変数で、右辺がパターン引数や変数がマッチした部分式の
等式のリストを返します。
パターン変数はそれらがマッチした部分式に割り当てられますが、
パターン引数には割り当てられません。
もしマッチが失敗したら、
@var{progname}は @code{false}を返します。

リテラルパターン(すなわち、パターン引数もパターン変数も含まないパターン)は、
もしマッチが成功したら、
@code{true}を返します。

@code{matchdeclare}, @code{defrule}, @code{tellsimp}, @code{tellsimpafter}も
参照してください。

例:

@code{a}と@code{b}は@code{x}を含まず、
@code{a}が非ゼロであるような
形式@code{a*x + b}かどうか見るために
@code{expr}をテストする
関数@code{linearp(expr, x)}を定義します。
パターン引数@code{x}が@code{defmatch}に与えられているので、
このマッチ関数は、
任意の変数に関する線形式にマッチします。
@c HOW HARD WILL MAXIMA TRY TO COLLECT TERMS AND DO OTHER MUNGEING TO FIT THE PATTERN ??

@c ===beg===
@c matchdeclare (a, lambda ([e], e#0 and freeof(x, e)), b, 
@c                     freeof(x));
@c defmatch (linearp, a*x + b, x);
@c linearp (3*z + (y + 1)*z + y^2, z);
@c a;
@c b;
@c x;
@c ===end===
@example
(%i1) matchdeclare (a, lambda ([e], e#0 and freeof(x, e)), b,
                    freeof(x));
(%o1)                         done
(%i2) defmatch (linearp, a*x + b, x);
(%o2)                        linearp
(%i3) linearp (3*z + (y + 1)*z + y^2, z);
                         2
(%o3)              [b = y , a = y + 4, x = z]
(%i4) a;
(%o4)                         y + 4
(%i5) b;
                                2
(%o5)                          y
(%i6) x;
(%o6)                           x
@end example

@code{a}と@code{b}は@code{x}を含まず、
@code{a}が非ゼロであるような
形式@code{a*x + b}かどうか見るために
@code{expr}をテストする
関数@code{linearp(expr, x)}を定義します。
@code{defmatch}にパターン引数が与えられていないので、
このマッチ関数は、
他の任意の変数ではなく変数@code{x}に関する線形式にマッチします。

@c ===beg===
@c matchdeclare (a, lambda ([e], e#0 and freeof(x, e)), b, 
@c                     freeof(x));
@c defmatch (linearp, a*x + b);
@c linearp (3*z + (y + 1)*z + y^2);
@c linearp (3*x + (y + 1)*x + y^2);
@c ===end===
@example
(%i1) matchdeclare (a, lambda ([e], e#0 and freeof(x, e)), b,
                    freeof(x));
(%o1)                         done
(%i2) defmatch (linearp, a*x + b);
(%o2)                        linearp
(%i3) linearp (3*z + (y + 1)*z + y^2);
(%o3)                         false
(%i4) linearp (3*x + (y + 1)*x + y^2);
                             2
(%o4)                  [b = y , a = y + 4]
@end example

定積分かどうか見るために
@code{expr}をテストする
関数@code{checklimits(expr)}を定義します。

@c ===beg===
@c matchdeclare ([a, f], true);
@c constinterval (l, h) := constantp (h - l);
@c matchdeclare (b, constinterval (a));
@c matchdeclare (x, atom);
@c simp : false;
@c defmatch (checklimits, 'integrate (f, x, a, b));
@c simp : true;
@c 'integrate (sin(t), t, %pi + x, 2*%pi + x);
@c checklimits (%);
@c ===end===
@example
(%i1) matchdeclare ([a, f], true);
(%o1)                         done
(%i2) constinterval (l, h) := constantp (h - l);
(%o2)        constinterval(l, h) := constantp(h - l)
(%i3) matchdeclare (b, constinterval (a));
(%o3)                         done
(%i4) matchdeclare (x, atom);
(%o4)                         done
(%i5) simp : false;
(%o5)                         false
(%i6) defmatch (checklimits, 'integrate (f, x, a, b));
(%o6)                      checklimits
(%i7) simp : true;
(%o7)                         true
(%i8) 'integrate (sin(t), t, %pi + x, 2*%pi + x);
@group
                       x + 2 %pi
                      /
                      [
(%o8)                 I          sin(t) dt
                      ]
                      /
                       x + %pi
@end group
(%i9) checklimits (%);
(%o9)    [b = x + 2 %pi, a = x + %pi, x = t, f = sin(t)]
@end example

@opencatbox
@category{Rules and patterns}
@closecatbox
@end deffn

@c NEEDS CLARIFICATION AND EXAMPLES

@c -----------------------------------------------------------------------------
@anchor{defrule}
@deffn {関数} defrule (@var{rulename}, @var{pattern}, @var{replacement})

与えられたパターンに関する置き換えルールを定義し、名付けます。
もし@var{rulename}と名付けられたルールが
(@code{apply1}, @code{applyb1}, @code{apply2}によって)
式に適用されるなら、
パターンにマッチするすべての部分式はreplacementで置き換えられます。
パターンマッチが値を割り当てるreplacementの中の変数すべては
その後整理される置き換えの中のそれらの値を割り当てられます。

ルールそれ自身は、
パターンマッチと置き換えの１演算で式を変換する
関数として扱うことができます。
マッチが失敗したら、ルール関数は@code{false}を返します。

@opencatbox
@category{Rules and patterns}
@closecatbox
@end deffn

@c NEEDS EXAMPLES

@c -----------------------------------------------------------------------------
@anchor{disprule}
@deffn  {関数} disprule (@var{rulename_1}, ..., @var{rulename_2})
@deffnx {関数} disprule (all)

@code{defrule}, @code{tellsimp}, @code{tellsimpafter}が返すような、または
@code{defmatch}が定義するパターンのような、
名前@var{rulename_1}, ..., @var{rulename_n}を持つルールを
表示します。
ルールそれぞれは中間式ラベル(@code{%t})と一緒に表示されます。

@code{disprule (all)}は、ルールすべてを表示します。

@code{disprule}は引数をクォートします。
@code{disprule}は、
表示されたルールに対応する中間式ラベルのリストを返します。

@code{let}が定義したルールを表示する
@code{letrules}も参照してください。

例:

@c ===beg===
@c tellsimpafter (foo (x, y), bar (x) + baz (y));
@c tellsimpafter (x + y, special_add (x, y));
@c defmatch (quux, mumble (x));
@c disprule (foorule1, "+rule1", quux);
@c ''%;
@c ===end===
@example
(%i1) tellsimpafter (foo (x, y), bar (x) + baz (y));
(%o1)                   [foorule1, false]
(%i2) tellsimpafter (x + y, special_add (x, y));
(%o2)                   [+rule1, simplus]
(%i3) defmatch (quux, mumble (x));
(%o3)                         quux
(%i4) disprule (foorule1, "+rule1", quux);
(%t4)        foorule1 : foo(x, y) -> baz(y) + bar(x)

(%t5)          +rule1 : y + x -> special_add(x, y)

(%t6)                quux : mumble(x) -> []

(%o6)                    [%t4, %t5, %t6]
(%i6) ''%;
(%o6) [foorule1 : foo(x, y) -> baz(y) + bar(x), 
     +rule1 : y + x -> special_add(x, y), quux : mumble(x) -> []]
@end example

@opencatbox
@category{Rules and patterns} @category{Display functions}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{let}
@deffn  {関数} let (@var{prod}, @var{repl}, @var{predname}, @var{arg_1}, ..., @var{arg_n})
@deffnx {関数} let ([@var{prod}, @var{repl}, @var{predname}, @var{arg_1}, ..., @var{arg_n}], @var{package_name})

@var{prod}は@var{repl}で置き換えられるような
@code{letsimp}のための代入ルールを定義します。
@var{prod}は、以下の項の正または負のべきの積です:

@itemize @bullet
@item
@code{letsimp}をコールする以前に@code{matchdeclare}関数が
述語論理をアトムと関連づけるために使われないなら、
@code{letsimp}が文字通りに検索するアトム。
この場合、@code{letsimp}はアトムを述語論理を満たす積の任意の項にマッチさせます。
@item
@code{sin(x)}, @code{n!}, @code{f(x,y)}などのようなカーネル。
上のアトムと同様に、
述語論理をカーネルの引数に関連づけるために
@code{matchdeclare}が使われないなら
@code{letsimp}は文字通りのマッチを検索します。
@end itemize

正のべきの項は、少なくともそのべきを持つ項だけにマッチするでしょう。
一方、負のべきの項は、少なくとも負としてのべきをもつ項だけにマッチするでしょう。
@var{prod}の中の負のべきの場合、
スイッチ@code{letrat}を@code{true}に設定しなければいけません。
@code{letrat}も参照してください。

もし述語論理が
引数のリストが続く@code{let}関数に含まれるなら、
@var{arg_i'}が@var{arg_i}にマッチした値である場合、
@code{predname (arg_1', ..., arg_n')}が@code{true}に評価される時だけ
試験的なマッチ(すなわち、述語論理が省略されたなら受け入れられるもの)
が受け入れられます。
@var{arg_i}は、任意のアトム名や
@var{prod}の中に現れる任意の核の引数を取り得ます。
@var{repl}は、任意の有理式を取り得ます。
@c ONLY RATIONAL -- REALLY ??
もし
任意のアトムや@var{prod}からの引数が@var{repl}の中に現れるなら、
適切な代入が行われます。
@c SPELL OUT "APPROPRIATE" IN THIS CONTEXT

グローバルフラグ@code{letrat}は、
@code{letsimp}による商の整理を制御します。
@code{letrat}が@code{false}の時、
@code{letsimp}は、
@var{expr}の分子と分母をそれぞれ整理し、章を整理はしません。
@code{n!/n}のような代入は@code{(n-1)!}に進み失敗します。
@code{letrat}が@code{true}の時、
分子、分母、商がその順番で整理されます。

これらの代入関数は、同時にいくつかのルールパッケージを使うことを許します。
ルールパッケージそれぞれは、
任意の数の@code{let}ルールを含むことができ、ユーザー定義名で参照されます。
コマンド@code{let ([@var{prod}, @var{repl}, @var{predname}, @var{arg_1},
..., @var{arg_n}], @var{package_name})}は、
ルール@var{predname}をルールパッケージ@var{package_name}に加えます。
コマンド@code{letsimp (@var{expr}, @var{package_name})} は、
@var{package_name}の中でルールを適用します。
@code{letsimp (@var{expr}, @var{package_name1}, @var{package_name2}, ...)}は、
@code{letsimp (%, @var{package_name2})}, @dots{}が続く
@code{letsimp (@var{expr}, @var{package_name1})}と同値です。

@code{current_let_rule_package}は、
現在使われているルールパッケージの名前です。
この変数は、
@code{let}コマンドを介して定義された任意のルールパッケージの名前に割れ当てられます。
@code{let}パッケージを構成する関数のいずれかがパッケージ名なしでコールされた時はいつでも
@code{current_let_rule_package}が指定したパッケージが使われます。
もし
@code{letsimp (@var{expr}, @var{rule_pkg_name})}のようなコールがされたら、
ルールパッケージ@var{rule_pkg_name}は、
その@code{letsimp}コマンドだけで使われ、
@code{current_let_rule_package}は変わりません。
もし他に指定されないなら、
@code{current_let_rule_package}は@code{default_let_rule_package}をデフォルト値とします。

@example
(%i1) matchdeclare ([a, a1, a2], true)$
(%i2) oneless (x, y) := is (x = y-1)$
(%i3) let (a1*a2!, a1!, oneless, a2, a1);
(%o3)         a1 a2! --> a1! where oneless(a2, a1)
(%i4) letrat: true$
(%i5) let (a1!/a1, (a1-1)!);
                        a1!
(%o5)                   --- --> (a1 - 1)!
                        a1
(%i6) letsimp (n*m!*(n-1)!/m);
(%o6)                      (m - 1)! n!
(%i7) let (sin(a)^2, 1 - cos(a)^2);
                        2               2
(%o7)                sin (a) --> 1 - cos (a)
(%i8) letsimp (sin(x)^4);
                        4           2
(%o8)                cos (x) - 2 cos (x) + 1
@end example

@c NEEDS ADDITIONAL EXAMPLES
@opencatbox
@category{Rules and patterns}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{letrat}
@defvr {オプション変数} letrat
デフォルト値: @code{false}

@code{letrat}が@code{false}の時、
@code{letsimp}は
比の分子と分母それぞれを整理し、
商を整理しません。

@code{letrat}が@code{true}の時、
分子、分母、商はその順番に整理されます。

@example
(%i1) matchdeclare (n, true)$
(%i2) let (n!/n, (n-1)!);
                         n!
(%o2)                    -- --> (n - 1)!
                         n
(%i3) letrat: false$
(%i4) letsimp (a!/a);
                               a!
(%o4)                          --
                               a
(%i5) letrat: true$
(%i6) letsimp (a!/a);
(%o6)                       (a - 1)!
@end example

@opencatbox
@category{Rules and patterns}
@closecatbox
@end defvr

@c NEEDS EXAMPLES

@c -----------------------------------------------------------------------------
@anchor{letrules}
@deffn  {関数} letrules ()
@deffnx {関数} letrules (@var{package_name})

ルールパッケージのルールを表示します。
@code{letrules ()}は現在のルールパッケージのルールを表示します。
@code{letrules (@var{package_name})}は
@var{package_name}のルールを表示します。

現在のルールパッケージは
@code{current_let_rule_package}によって指名されます。
もし他に指定されないなら、
@code{current_let_rule_package}は@code{default_let_rule_package}がデフォルト値になります。

@code{disprule}も参照してください
それは、
@code{tellsimp}と@code{tellsimpafter}が定義するルールを表示します。
@c WHAT ABOUT defmatch AND defrule ??

@opencatbox
@category{Rules and patterns}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{letsimp}
@deffn  {関数} letsimp (@var{expr})
@deffnx {関数} letsimp (@var{expr}, @var{package_name})
@deffnx {関数} letsimp (@var{expr}, @var{package_name_1}, @dots{}, @var{package_name_n})

@var{expr}に変化がなくなるまで
繰り返し、@code{let}が定義する代入ルールを適用します。

@code{letsimp (@var{expr})}は
@code{current_let_rule_package}からルールを使います。

@code{letsimp (@var{expr}, @var{package_name})}は、
@code{current_let_rule_package}を変えることなしに
@var{package_name}からルールを使います。

@code{letsimp (@var{expr}, @var{package_name_1}, ..., @var{package_name_n})}は、
quivalent to 
@code{letsimp (%, @var{package_name_2})}などが続く
@code{letsimp (@var{expr}, @var{package_name_1}}と同値です。

@c NEEDS EXAMPLES
@opencatbox
@category{Rules and patterns}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{let_rule_packages}
@defvr {オプション変数} let_rule_packages
デフォルト値: @code{[default_let_rule_package]}

@code{let_rule_packages}は、
デフォルトパッケージ@code{default_let_rule_package}に加える
ユーザー定義のletルールパッケージすべてのリストです。

@opencatbox
@category{Rules and patterns}
@closecatbox
@end defvr

@c -----------------------------------------------------------------------------
@anchor{matchdeclare}
@deffn {関数} matchdeclare (@var{a_1}, @var{pred_1}, ..., @var{a_n}, @var{pred_n})

述語論理 @var{pred_k}を変数 @var{a_k}の変数やリストに関連づけます。
なので、 @var{a_k}は述語論理が @code{false}以外の何かを返す式にマッチします。

述語論理は関数の名前、ラムダ式、関数コール、最後の引数のないラムダコール、
@code{true}または @code{all}です。
任意の式が @code{true}や @code{all}にマッチします。
もし述語論理が関数コールかラムダコールとして指定されるなら、
テストされる式が引数のリストに追加されます;
マッチが評価される時引数が評価されます。
そうでないなら、述語論理は関数名またはラムダ式として指定され、
テストされる式が唯一の引数です。
@code{matchdeclare}がコールされた時、述語論理関数は定義されている必要はありません;
述語論理はマッチが試みられるまで評価されません。

述語論理は、
@code{true}か @code{false}はもちろん、ブーリアン式を返すかもしれません。
ブーリアン式は、構成されたルール関数内で @code{is}によって評価されるので、
述語論理内部で @code{is}をコールする必要はありません。

もし式がマッチ述語論理を満たすなら、
マッチ変数が式に割り当てられます。
例外は足し算 @code{+}や掛け算 @code{*}のオペランドのマッチ変数です。
足し算と掛け算だけは特別に扱われます;
他のn項演算子(組み込みもユーザー定義も)は通常の関数のように扱われます。
@c WOULD BE GREAT TO EXTEND PART+/PART* PROCESSING TO ALL N-ARY OPERATORS

足し算と掛け算の場合、
マッチ変数はマッチ述語論理を満たす唯一の式か、
そんな式の(それぞれ)和または積に割り当てられます。
そんな多項マッチングはどん欲(greedy)です:
述語論理群はそれらの関連変数がマッチパターンの中で現れる順に評価され、
複数の述語論理を満たす項は、それが満たす最初の述語論理によってマッチされます。
述語論理それぞれは、
次の述語論理が評価される前に
和や積のオペランドすべてに対してテストされます。
加えて、
もし(それぞれ)0か1がマッチ述語論理を満たし、かつ、
述語論理を満たす他の項がないなら、
0か1が述語論理の関連マッチ変数に割り当てられます。

足し算と掛け算パターンを処理するアルゴリズムは、
(例えば、「任意のものにマッチする」変数が現れるパターンのように)
マッチパターンの中やマッチされる式の中の項の順序付けに依存したいくつかのマッチ結果をもたらします。
しかしながら、もしマッチ述語論理すべてが相互に排他的なら、
１つのマッチ述語論理はべつのものがマッチした項を受け入れられないので、
マッチ結果は順序付けに影響されません。

変数 @var{a}を引数として @code{matchdeclare}をコールすると、
もし既に宣言されているなら、
@var{a}に関する @code{matchdeclare}プロパティが変わります:
ルールが定義された時、直近の @code{matchdeclare}だけが効果を持ちます。
(@code{matchdeclare}か @code{remove}を介した)
@code{matchdeclare}プロパティへの後の変更は、存在するルールに影響しません。

@code{propvars (matchdeclare)}は
@code{matchdeclare}プロパティを持つ変数すべてのリストを返します。
@code{printprops (@var{a}, matchdeclare)}は、
変数 @code{a}に関する述語論理を返します。
@code{printprops (all, matchdeclare)}は、
すべての @code{matchdeclare}変数に関する述語論理のリストを返します。
@code{remove (@var{a}, matchdeclare)}は、
@var{a}から @code{matchdeclare}プロパティを削除します。

関数 @code{defmatch}, @code{defrule}, @code{tellsimp}, @code{tellsimpafter}, @code{let}は、パターンに対して式をテストするルールを構成します。

@code{matchdeclare}は引数をクォートします。
@code{matchdeclare}はいつも @code{done}を返します。

例:

述語論理は、関数名か、ラムダ式か、最後の引数がない関数コールかラムダコールか、
@code{true}か @code{all}です。

@c ===beg===
@c matchdeclare (aa, integerp);
@c matchdeclare (bb, lambda ([x], x > 0));
@c matchdeclare (cc, freeof (%e, %pi, %i));
@c matchdeclare (dd, lambda ([x, y], gcd (x, y) = 1) (1728));
@c matchdeclare (ee, true);
@c matchdeclare (ff, all);
@c ===end===
@example
(%i1) matchdeclare (aa, integerp);
(%o1)                         done
(%i2) matchdeclare (bb, lambda ([x], x > 0));
(%o2)                         done
(%i3) matchdeclare (cc, freeof (%e, %pi, %i));
(%o3)                         done
(%i4) matchdeclare (dd, lambda ([x, y], gcd (x, y) = 1) (1728));
(%o4)                         done
(%i5) matchdeclare (ee, true);
(%o5)                         done
(%i6) matchdeclare (ff, all);
(%o6)                         done
@end example

もし式がマッチ述語論理を満たすなら、
マッチ変数は式に割り当てられます。

@c ===beg===
@c matchdeclare (aa, integerp, bb, atom);
@c defrule (r1, bb^aa, ["integer" = aa, "atom" = bb]);
@c r1 (%pi^8);
@c ===end===
@example
(%i1) matchdeclare (aa, integerp, bb, atom);
(%o1)                         done
(%i2) defrule (r1, bb^aa, ["integer" = aa, "atom" = bb]);
                    aa
(%o2)        r1 : bb   -> [integer = aa, atom = bb]
(%i3) r1 (%pi^8);
(%o3)               [integer = 8, atom = %pi]
@end example

足し算と掛け算の場合、
マッチ変数は、マッチ述語論理を満たす１つの式か、
そんな式の(それぞれ)和か積に割り当てられるかもしれません。

@c ===beg===
@c matchdeclare (aa, atom, bb, lambda ([x], not atom(x)));
@c defrule (r1, aa + bb, ["all atoms" = aa, "all nonatoms" = 
@c                bb]);
@c r1 (8 + a*b + sin(x));
@c defrule (r2, aa * bb, ["all atoms" = aa, "all nonatoms" = 
@c                bb]);
@c r2 (8 * (a + b) * sin(x));
@c ===end===
@example
(%i1) matchdeclare (aa, atom, bb, lambda ([x], not atom(x)));
(%o1)                         done
(%i2) defrule (r1, aa + bb, ["all atoms" = aa, "all nonatoms" =
               bb]);
bb + aa partitions `sum'
(%o2)  r1 : bb + aa -> [all atoms = aa, all nonatoms = bb]
(%i3) r1 (8 + a*b + sin(x));
(%o3)     [all atoms = 8, all nonatoms = sin(x) + a b]
(%i4) defrule (r2, aa * bb, ["all atoms" = aa, "all nonatoms" =
               bb]);
bb aa partitions `product'
(%o4)   r2 : aa bb -> [all atoms = aa, all nonatoms = bb]
(%i5) r2 (8 * (a + b) * sin(x));
(%o5)    [all atoms = 8, all nonatoms = (b + a) sin(x)]
@end example

@code{+}と @code{*}の引数をマッチする時、
もしマッチ述語論理すべてが相互に排他的なら、
１つのマッチ述語論理は別のものがマッチした項を受け入れられないので、
マッチ結果は順序付けに影響されません。

@c ===beg===
@c matchdeclare (aa, atom, bb, lambda ([x], not atom(x)));
@c defrule (r1, aa + bb, ["all atoms" = aa, "all nonatoms" = 
@c                bb]);
@c r1 (8 + a*b + %pi + sin(x) - c + 2^n);
@c defrule (r2, aa * bb, ["all atoms" = aa, "all nonatoms" = 
@c                bb]);
@c r2 (8 * (a + b) * %pi * sin(x) / c * 2^n);
@c ===end===
@example
(%i1) matchdeclare (aa, atom, bb, lambda ([x], not atom(x)));
(%o1)                         done
(%i2) defrule (r1, aa + bb, ["all atoms" = aa, "all nonatoms" =
               bb]);
bb + aa partitions `sum'
(%o2)  r1 : bb + aa -> [all atoms = aa, all nonatoms = bb]
(%i3) r1 (8 + a*b + %pi + sin(x) - c + 2^n);
                                                     n
(%o3) [all atoms = %pi + 8, all nonatoms = sin(x) + 2  - c + a b]
(%i4) defrule (r2, aa * bb, ["all atoms" = aa, "all nonatoms" =
               bb]);
bb aa partitions `product'
(%o4)   r2 : aa bb -> [all atoms = aa, all nonatoms = bb]
(%i5) r2 (8 * (a + b) * %pi * sin(x) / c * 2^n);
                                                  n
                                         (b + a) 2  sin(x)
(%o5) [all atoms = 8 %pi, all nonatoms = -----------------]
                                                 c
@end example

関数 @code{propvars}と @code{printprops}はマッチ変数についての情報を返します。

@c ===beg===
@c matchdeclare ([aa, bb, cc], atom, [dd, ee], integerp);
@c matchdeclare (ff, floatnump, gg, lambda ([x], x > 100));
@c propvars (matchdeclare);
@c printprops (ee, matchdeclare);
@c printprops (gg, matchdeclare);
@c printprops (all, matchdeclare);
@c ===end===
@example
(%i1) matchdeclare ([aa, bb, cc], atom, [dd, ee], integerp);
(%o1)                         done
(%i2) matchdeclare (ff, floatnump, gg, lambda ([x], x > 100));
(%o2)                         done
(%i3) propvars (matchdeclare);
(%o3)             [aa, bb, cc, dd, ee, ff, gg]
(%i4) printprops (ee, matchdeclare);
(%o4)                    [integerp(ee)]
(%i5) printprops (gg, matchdeclare);
(%o5)              [lambda([x], x > 100, gg)]
(%i6) printprops (all, matchdeclare);
(%o6) [lambda([x], x > 100, gg), floatnump(ff), integerp(ee), 
                      integerp(dd), atom(cc), atom(bb), atom(aa)]
@end example

@opencatbox
@category{Rules and patterns} @category{Declarations and inferences}
@closecatbox
@end deffn

@c NEEDS EXAMPLES

@c -----------------------------------------------------------------------------
@anchor{maxapplydepth}
@defvr {オプション変数} maxapplydepth
デフォルト値: 10000

@code{maxapplydepth}は
@code{apply1}と @code{apply2}が探索する
最大深さです。

@opencatbox
@category{Function application}
@closecatbox
@end defvr

@c NEEDS EXAMPLES

@c -----------------------------------------------------------------------------
@anchor{maxapplyheight}
@defvr {オプション変数} maxapplyheight
デフォルト値: 10000

@code{maxapplyheight}は
@code{applyb1}があきらめる前に到達する
最大高さです。

@opencatbox
@category{Function application}
@closecatbox
@end defvr

@c NEEDS CLARIFICATION AND EXAMPLES

@c -----------------------------------------------------------------------------
@anchor{remlet}
@deffn  {関数} remlet (@var{prod}, @var{name})
@deffnx {関数} remlet ()
@deffnx {関数} remlet (all)
@deffnx {関数} remlet (all, @var{name})

@code{let}関数で直近に定義された
代入ルール@var{prod} --> replを削除します。
もし名前が供給されるなら、ルールはルールパッケージ名から削除されます。

@code{remlet()}や@code{remlet(all)}は
現在のルールパッケージから代入ルールすべてを削除します。
もし例えば、@code{remlet (all, @var{name})}にように、ルールパッケージ名が供給されるなら、
ルールパッケージ@var{name}も削除されます。

もし代入が同じ積を使って変更されるなら、
@code{remlet}はコールされる必要はなく、
@code{let}関数と新しい置き換え　かつ/または述語論理名で、文字通りに同じ積を使って代入を再定義だけです。
さて、@code{remlet (@var{prod})}がコールされると、
元の代入ルールが生き返ります。

@code{remrule}も参照してください。
@code{tellsimp}や@code{tellsimpafter}で定義されたルールを削除します。

@opencatbox
@category{Rules and patterns}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{remrule}
@deffn {関数} remrule (@var{op}, @var{rulename})
@deffnx {関数} remrule (@var{op}, all)

@code{tellsimp}や@code{tellsimpafter}で定義されたルールを削除します。

@code{remrule (@var{op}, @var{rulename})}は、
演算子@var{op}から
名前@var{rulename}を持つ
ルールを削除します。
@var{op}が組み込みか
(@code{infix}, @code{prefix}, などで定義されたような)ユーザー定義演算子の時、
@var{op}と@var{rulename}はダブルクォートマークでくくられないといけません。

@code{remrule (@var{op}, all)}は
演算子@var{op}に関するルールすべてを削除します。

@code{remlet}も参照してください。
@code{let}で定義されたルールを削除します。

例:

@c ===beg===
@c tellsimp (foo (aa, bb), bb - aa);
@c tellsimpafter (aa + bb, special_add (aa, bb));
@c infix ("@@");
@c tellsimp (aa @@ bb, bb/aa);
@c tellsimpafter (quux (%pi, %e), %pi - %e);
@c tellsimpafter (quux (%e, %pi), %pi + %e);
@c [foo (aa, bb), aa + bb, aa @@ bb, quux (%pi, %e), 
@c        quux (%e, %pi)];
@c remrule (foo, foorule1);
@c remrule ("+", ?\+rule1);
@c remrule ("@@", ?\@\@rule1);
@c remrule (quux, all);
@c [foo (aa, bb), aa + bb, aa @@ bb, quux (%pi, %e), 
@c         quux (%e, %pi)];
@c ===end===
@example
(%i1) tellsimp (foo (aa, bb), bb - aa);
(%o1)                   [foorule1, false]
(%i2) tellsimpafter (aa + bb, special_add (aa, bb));
(%o2)                   [+rule1, simplus]
(%i3) infix ("@@@@");
(%o3)                          @@@@
(%i4) tellsimp (aa @@@@ bb, bb/aa);
(%o4)                   [@@@@rule1, false]
(%i5) tellsimpafter (quux (%pi, %e), %pi - %e);
(%o5)                  [quuxrule1, false]
(%i6) tellsimpafter (quux (%e, %pi), %pi + %e);
(%o6)             [quuxrule2, quuxrule1, false]
(%i7) [foo (aa, bb), aa + bb, aa @@@@ bb, quux (%pi, %e),
       quux (%e, %pi)];
                                     bb
(%o7) [bb - aa, special_add(aa, bb), --, %pi - %e, %pi + %e]
                                     aa
(%i8) remrule (foo, foorule1);
(%o8)                          foo
(%i9) remrule ("+", ?\+rule1);
(%o9)                           +
(%i10) remrule ("@@@@", ?\@@\@@rule1);
(%o10)                         @@@@
(%i11) remrule (quux, all);
(%o11)                        quux
(%i12) [foo (aa, bb), aa + bb, aa @@@@ bb, quux (%pi, %e),
        quux (%e, %pi)];
(%o12) [foo(aa, bb), bb + aa, aa @@@@ bb, quux(%pi, %e), 
                                         quux(%e, %pi)]
@end example

@opencatbox
@category{Rules and patterns}
@closecatbox
@end deffn

@c NEEDS EXPANSION OR MAYBE JUST APPROPRIATE REFS TO tellsimpafter

@c -----------------------------------------------------------------------------
@anchor{tellsimp}
@deffn {関数} tellsimp (@var{pattern}, @var{replacement})

@code{tellsimpafter}に似ていますが、
古いものの前に新しい情報を置くので、
組み込み整理ルールの前に適用されます。

整理器が働く前に式を変更することが重要な時
例えば、整理器が式について何か「知っている」が、それが返すものが好みでないなら、
@code{tellsimp}が使われます。
もし整理器が式の主演算子について何かを「知っている」が、単に十分でないなら、
たぶん@code{tellsimpafter}を使いたいでしょう。

パターンは和、積、変数１つ、または、数は取れません。

システム変数@code{rules}は、
@code{defrule}, @code{defmatch}, @code{tellsimp}, @code{tellsimpafter}で
定義されたルールのリストです。

例:

@example
(%i1) matchdeclare (x, freeof (%i));
(%o1)                         done
(%i2) %iargs: false$
(%i3) tellsimp (sin(%i*x), %i*sinh(x));
(%o3)                 [sinrule1, simp-%sin]
(%i4) trigexpand (sin (%i*y + x));
(%o4)         sin(x) cos(%i y) + %i cos(x) sinh(y)
(%i5) %iargs:true$
(%i6) errcatch(0^0);
 0
0  has been generated
(%o6)                          []
(%i7) ev (tellsimp (0^0, 1), simp: false);
(%o7)                  [^rule1, simpexpt]
(%i8) 0^0;
(%o8)                           1
(%i9) remrule ("^", %th(2)[1]);
(%o9)                           ^
(%i10) tellsimp (sin(x)^2, 1 - cos(x)^2);
(%o10)                 [^rule2, simpexpt]
(%i11) (1 + sin(x))^2;
                                      2
(%o11)                    (sin(x) + 1)
(%i12) expand (%);
                                   2
(%o12)               2 sin(x) - cos (x) + 2
(%i13) sin(x)^2;
                                  2
(%o13)                     1 - cos (x)
(%i14) kill (rules);
(%o14)                        done
(%i15) matchdeclare (a, true);
(%o15)                        done
(%i16) tellsimp (sin(a)^2, 1 - cos(a)^2);
(%o16)                 [^rule3, simpexpt]
(%i17) sin(y)^2;
                                  2
(%o17)                     1 - cos (y)
@end example

@opencatbox
@category{Rules and patterns}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{tellsimpafter}
@deffn {関数} tellsimpafter (@var{pattern}, @var{replacement})

組み込み整理ルールの後、適Maxima整理器が適用する
整理ルールを定義します。
@var{pattern}は
(@code{matchdeclare}で宣言された)
パターン変数や他のアトムや演算子から成る、
パターンマッチングの目的でリテラルと考えられる式です。
@var{replacement}は、
@var{pattern}にマッチする実際の式に代入されます;
@var{replacement}の中のパターン変数は
実際の式の中でマッチした値に割り当てられます。

@var{pattern}は、
主演算子がパターン変数でない任意の非アトム式を取り得ます;
整理ルールは主演算子に関連付けられます。
(以下で記述する１つの例外がありますが、)関数、リスト、配列の名前が、
(パターン変数でなく)ただリテラルとして、
主演算子として@var{pattern}の中で現れることができます;
これは、
パターンとして
もし@code{aa}や@code{bb}がパターン変数なら
@code{aa(x)}や@code{bb[y]}のような式を除外します。
パターン変数である関数、リスト、配列の名前は、
@var{pattern}の中で、主演算子以外の演算子として現れることができます。

上の関数名に関するルールに１つ例外があります。
@code{aa[x](y)}のような式の中の添字付き関数の名前は
主演算子が@code{aa}でなくLispアトム@code{mqapply}だから、
パターン変数にできます。
これは、添字付き関数を含む式の表現の結果です。

@c LET'S NOT GO INTO DETAILS ABOUT MAIN OPERATORS HERE; BUT PRESERVE THIS FOR REFERENCE
@c The main operator of an expression @code{expr} is @code{caar $expr}.
@c For most kinds of expressions,
@c the main operator is the operator returned by @code{op (@var{pattern})};
@c the sole exception is the operator @code{mqapply},
@c which appears in indexed function expressions (e.g., @code{foo[i](x)}).

@c NEED TO REVIEW THIS PARAGRAPH FOR ACCURACY
(もしクォートやフラグ@code{noeval}を通して抑制されないなら)
整理ルールは、
評価の後、適用されます。
@code{tellsimpafter}で確立されたルールは、
組み込みルールの後、それらが定義された順に適用されます。
ルールはボトムアップに適用されます。すなわち、
式全体への適用の前に、最初、部分式に適用されます。
@c NO IT IS MORE COMPLICATED THAN THIS, ALTHOUGH IN SOME CIRCUMSTANCE IT APPEARS TO BE THE CASE:
@c For a given expression, at most one rule per operator is applied.
ルールすべてが適用されることを保証するために、
(例えば、クォートクォート演算子@code{'@w{}'}やフラグ@code{infeval}を介して)
結果を繰り返し整理する必要があるかもしれません。

パターン変数は、整理ルールの中でローカル変数として扱われます。
一旦ルールが定義されると、パターン変数の値は、
ルールに影響せず、ルールによって影響されません。
成功したルールマッチの結果となるパターン変数への割り当ては、
パターン変数の現在の割り当て(またはその欠落)に影響しません。
しかしながら、Maximaの中のアトムすべてで、
(@code{put}や関連関数で定義された)パターン変数のプロパティはグローバルです。

@code{tellsimpafter}によって構成されたルールは、
@var{pattern}の主演算子に由来します。
組み込み演算子や
@code{infix}, @code{prefix}, @code{postfix}, @code{matchfix}, @code{nofix}で
定義されたユーザー定義演算子に関するルールは、
Lisp識別子である名前を持ちます。
@c SLIGHTLY TOO MUCH DETAIL
@c (that is, the name is written with a leading question mark @code{?} in Maxima).
他の関数に関するルールは、Maxima識別子である名前を持ちます。
@c SLIGHTLY TOO MUCH DETAIL
@c (that is, the name begins with dollar sign @code{$}).

名詞と動詞形の扱いは少し混乱しています。
@c THIS IS A BUG.
もしルールが名詞(または動詞)形に関して定義されて、
対応する動詞(または名詞)形に関するルールが既に存在しているなら、
新しく定義されたルールは両方の形式(名詞と動詞)に適用されます。
もし対応する動詞(名詞)形に関するルールが存在しないなら、
新しく定義されたルールは名詞(または動詞)形にだけ適用されます。

@code{tellsimpafter}で構成されたルールは通常のLisp関数です。
もしルール名が@code{$foorule1}なら、
構成子@code{:lisp (trace $foorule1)}は関数をトレースし、
@code{:lisp (symbol-function '$foorule1)}は定義を表示します。

@code{tellsimpafter}は引数をクォートします。
@code{tellsimpafter}は
新しく確立されたルールを含む、
@var{pattern}の主演算子に関する
ルールのリストを返します。
@c WHAT IS simpfoo THAT SOMETIMES APPEARS, AND WHY DOES false SOMETIMES APPEAR IN RETURN VALUE ??

@code{matchdeclare}, @code{defmatch}, @code{defrule}, @code{tellsimp}, @code{let}, @code{kill}, @code{remrule}, @code{clear_rules}も参照してください。

例:

@var{pattern}は、
主演算子がパターン変数でない任意の非アトム式を取り得ます。

@c ===beg===
@c matchdeclare (aa, atom, [ll, mm], listp, xx, true)$
@c tellsimpafter (sin (ll), map (sin, ll));
@c sin ([1/6, 1/4, 1/3, 1/2, 1]*%pi);
@c tellsimpafter (ll^mm, map ("^", ll, mm));
@c [a, b, c]^[1, 2, 3];
@c tellsimpafter (foo (aa (xx)), aa (foo (xx)));
@c foo (bar (u - v));
@c ===end===
@example
(%i1) matchdeclare (aa, atom, [ll, mm], listp, xx, true)$
(%i2) tellsimpafter (sin (ll), map (sin, ll));
(%o2)                 [sinrule1, simp-%sin]
(%i3) sin ([1/6, 1/4, 1/3, 1/2, 1]*%pi);
                    1  sqrt(2)  sqrt(3)
(%o3)              [-, -------, -------, 1, 0]
                    2     2        2
(%i4) tellsimpafter (ll^mm, map ("^", ll, mm));
(%o4)                  [^rule1, simpexpt]
(%i5) [a, b, c]^[1, 2, 3];
                                2   3
(%o5)                      [a, b , c ]
(%i6) tellsimpafter (foo (aa (xx)), aa (foo (xx)));
(%o6)                   [foorule1, false]
(%i7) foo (bar (u - v));
(%o7)                    bar(foo(u - v))
@end example

ルールはそれらが定義された順に適用されます。
もし２つのルールが式にマッチできるなら、
最初に定義されたルールが適用されます。

@c ===beg===
@c matchdeclare (aa, integerp);
@c tellsimpafter (foo (aa), bar_1 (aa));
@c tellsimpafter (foo (aa), bar_2 (aa));
@c foo (42);
@c ===end===
@example
(%i1) matchdeclare (aa, integerp);
(%o1)                         done
(%i2) tellsimpafter (foo (aa), bar_1 (aa));
(%o2)                   [foorule1, false]
(%i3) tellsimpafter (foo (aa), bar_2 (aa));
(%o3)              [foorule2, foorule1, false]
(%i4) foo (42);
(%o4)                       bar_1(42)
@end example

整理ルールの中で、パターン変数はローカル変数として扱われます。
(@code{defmatch}と比較してください。
パターン変数をグローバル変数として扱います。)

@c ===beg===
@c matchdeclare (aa, integerp, bb, atom);
@c tellsimpafter (foo(aa, bb), bar('aa=aa, 'bb=bb));
@c bb: 12345;
@c foo (42, %e);
@c bb;
@c ===end===
@example
(%i1) matchdeclare (aa, integerp, bb, atom);
(%o1)                         done
(%i2) tellsimpafter (foo(aa, bb), bar('aa=aa, 'bb=bb));
(%o2)                   [foorule1, false]
(%i3) bb: 12345;
(%o3)                         12345
(%i4) foo (42, %e);
(%o4)                 bar(aa = 42, bb = %e)
(%i5) bb;
(%o5)                         12345
@end example

アトムすべてには、
パターン変数のプロパティは、たとえ値がローカルでも、
グローバルです。
この例では、割り当てプロパティは
@code{define_variable}を介して宣言されます。
Maximaの至る所で、これはアトム@code{bb}のプロパティです。

@c ===beg===
@c matchdeclare (aa, integerp, bb, atom);
@c tellsimpafter (foo(aa, bb), bar('aa=aa, 'bb=bb));
@c foo (42, %e);
@c define_variable (bb, true, boolean);
@c foo (42, %e);
@c ===end===
@example
(%i1) matchdeclare (aa, integerp, bb, atom);
(%o1)                         done
(%i2) tellsimpafter (foo(aa, bb), bar('aa=aa, 'bb=bb));
(%o2)                   [foorule1, false]
(%i3) foo (42, %e);
(%o3)                 bar(aa = 42, bb = %e)
(%i4) define_variable (bb, true, boolean);
(%o4)                         true
(%i5) foo (42, %e);
Error: bb was declared mode boolean, has value: %e
 -- an error.  Quitting.  To debug this try debugmode(true);
@end example

ルールは主演算子に由来します。
組み込みやユーザー定義の演算子に関するルール名はLisp識別子で、
一方、他の関数に関する名前はMaxima識別子です。

@c ===beg===
@c tellsimpafter (foo (%pi + %e), 3*%pi);
@c tellsimpafter (foo (%pi * %e), 17*%e);
@c tellsimpafter (foo (%i ^ %e), -42*%i);
@c tellsimpafter (foo (9) + foo (13), quux (22));
@c tellsimpafter (foo (9) * foo (13), blurf (22));
@c tellsimpafter (foo (9) ^ foo (13), mumble (22));
@c rules;
@c foorule_name: first (%o1);
@c plusrule_name: first (%o4);
@c remrule (foo, foorule1);
@c remrule ("^", ?\^rule1);
@c rules;
@c ===end===
@example
(%i1) tellsimpafter (foo (%pi + %e), 3*%pi);
(%o1)                   [foorule1, false]
(%i2) tellsimpafter (foo (%pi * %e), 17*%e);
(%o2)              [foorule2, foorule1, false]
(%i3) tellsimpafter (foo (%i ^ %e), -42*%i);
(%o3)         [foorule3, foorule2, foorule1, false]
(%i4) tellsimpafter (foo (9) + foo (13), quux (22));
(%o4)                   [+rule1, simplus]
(%i5) tellsimpafter (foo (9) * foo (13), blurf (22));
(%o5)                  [*rule1, simptimes]
(%i6) tellsimpafter (foo (9) ^ foo (13), mumble (22));
(%o6)                  [^rule1, simpexpt]
(%i7) rules;
(%o7) [foorule1, foorule2, foorule3, +rule1, *rule1, ^rule1]
(%i8) foorule_name: first (%o1);
(%o8)                       foorule1
(%i9) plusrule_name: first (%o4);
(%o9)                        +rule1
(%i10) remrule (foo, foorule1);
(%o10)                         foo
(%i11) remrule ("^", ?\^rule1);
(%o11)                          ^
(%i12) rules;
(%o12)        [foorule2, foorule3, +rule1, *rule1]
@end example

加工された例: 反可換乗算。

@c ===beg===
@c gt (i, j) := integerp(j) and i < j;
@c matchdeclare (i, integerp, j, gt(i));
@c tellsimpafter (s[i]^^2, 1);
@c tellsimpafter (s[i] . s[j], -s[j] . s[i]);
@c s[1] . (s[1] + s[2]);
@c expand (%);
@c factor (expand (sum (s[i], i, 0, 9)^^5));
@c ===end===
@example
(%i1) gt (i, j) := integerp(j) and i < j;
(%o1)           gt(i, j) := integerp(j) and i < j
(%i2) matchdeclare (i, integerp, j, gt(i));
(%o2)                         done
(%i3) tellsimpafter (s[i]^^2, 1);
(%o3)                 [^^rule1, simpncexpt]
(%i4) tellsimpafter (s[i] . s[j], -s[j] . s[i]);
(%o4)                   [.rule1, simpnct]
(%i5) s[1] . (s[1] + s[2]);
(%o5)                    s  . (s  + s )
                          1     2    1
(%i6) expand (%);
(%o6)                      1 - s  . s
                                2    1
(%i7) factor (expand (sum (s[i], i, 0, 9)^^5));
(%o7) 100 (s  + s  + s  + s  + s  + s  + s  + s  + s  + s )
            9    8    7    6    5    4    3    2    1    0
@end example

@opencatbox
@category{Rules and patterns}
@closecatbox
@end deffn

@c -----------------------------------------------------------------------------
@anchor{clear_rules}
@deffn {関数} clear_rules ()

@code{kill (rules)}を実行し、
足し算@code{+}, 掛け算@code{*}, べき@code{^}に関して
次のルール番号を1に再設定します。

@opencatbox
@category{Rules and patterns}
@closecatbox
@end deffn
