Previous: Assignment operators, Up: Operators   [Contents][Index]

7.7 User defined operators

関数: infix (op)
関数: infix (op, lbp, rbp)
関数: infix (op, lbp, rbp, lpos, rpos, pos)

opを中置演算子に宣言します。 中置演算子は2つの引数の関数で、引数の間に関数名が来ます。 例えば、引き算演算子-は中置演算子です。

infix (op)は、デフォルトの結合力(左右両方とも180)と品詞 (左右両方ともany)に等しい)でopを中置演算子に宣言します。

infix (op, lbp, rbp)は、 記述された左右の結合力 とデフォルトの品詞(左右両方ともany)に等しい)で、 opを中置演算子に宣言します。

infix (op, lbp, rbp, lpos, rpos, pos)は、 記述された左右の結合力と、 左オペランド、右オペランド、演算子結果それぞれについて、 品詞をlpos, rpos, posに設定して、 opを中置演算子に宣言します。

(演算子宣言に関係して)「品詞」は、式のタイプを意味します。 3つのタイプが認識されます; expr, clause, any。それぞれは、 代数式、ブーリアン式、任意の種類の式を示します。 Maximaは、宣言された品詞を実際の式に比較することで、 いくつかの構文法エラーを検出します。

他の演算子に関するopの優先順位は、問題となっている演算子の左右結合力から演繹されます。 もしopの左右結合力のどちらもある他の演算子の左右結合力より大きいなら、 opは、他の演算子より高い優先順位をとります。 もし結合力がどちらも大きくも、どちらも小さくもなければ、 あるもっと複雑な関係が成り立ちます。

opの結合性は結合力に依存します。 より大きな左結合力(lbp)は、opのインスタンスが 式の中で左にある他の演算子の前に評価されることを示し、 より大きな右結合力(rbp)は、opのインスタンスが 式の中で右にある他の演算子の前に評価されることを示します。 このように、より大きなlbpopを右結合にし、 より大きなrbpopを左結合にします。 もしlbprbpと等しいなら、 opは左結合です。

Syntaxも参照してください。

例:

もしop左右結合力それぞれが、他の演算子のそれより大きいなら、 opは他の演算子より高い優先順位をとります。

(%i1) :lisp (get '$+ 'lbp)
100
(%i1) :lisp (get '$+ 'rbp)
100
(%i1) infix ("##", 101, 101);
(%o1)                          ##
(%i2) "##"(a, b) := sconcat("(", a, ",", b, ")");
(%o2)       (a ## b) := sconcat("(", a, ",", b, ")")
(%i3) 1 + a ## b + 2;
(%o3)                       (a,b) + 3
(%i4) infix ("##", 99, 99);
(%o4)                          ##
(%i5) 1 + a ## b + 2;
(%o5)                       (a+1,b+2)

より大きなlbpopを右結合にし、 より大きなrbpopを左結合にします。

(%i1) infix ("##", 100, 99);
(%o1)                          ##
(%i2) "##"(a, b) := sconcat("(", a, ",", b, ")")$
(%i3) foo ## bar ## baz;
(%o3)                    (foo,(bar,baz))
(%i4) infix ("##", 100, 101);
(%o4)                          ##
(%i5) foo ## bar ## baz;
(%o5)                    ((foo,bar),baz)

Maximaは、宣言された品詞を実際の式と比較することで、 いくつかの構文法エラーを検出します。

(%i1) infix ("##", 100, 99, expr, expr, expr);
(%o1)                          ##
(%i2) if x ## y then 1 else 0;
Incorrect syntax: Found algebraic expression where logical
expression expected
if x ## y then 
             ^
(%i2) infix ("##", 100, 99, expr, expr, clause);
(%o2)                          ##
(%i3) if x ## y then 1 else 0;
(%o3)                if x ## y then 1 else 0
関数: matchfix (ldelimiter, rdelimiter)
関数: matchfix (ldelimiter, rdelimiter, arg_pos, pos)

左と右の区切り記号ldelimiterrdelimiterを持つ matchfix演算子を宣言します 区切り記号は文字列として指定されます。

"matchfix"演算子は、 任意の数の引数の関数で、引数は左と右の区切り記号をマッチする間で現れます。 パーサがオペランドや他の式や演算子から区切り記号を区別できる限り 区切り記号は任意の文字列を取り得ます。 実際には、これは、%, ,, $, ;のような パースできない区切り記号を除外し、空白を持つ区切り記号を分離することを要求するかもしれません。 右区切り記号は、左区切り記号と同じかもしれませんし、違うかもしれません。

左区切り記号は、たった1つの右区切り記号と関連づけられることができます; 2つの異なるmatchfix演算子は同じ左区切り記号を持つことはできません。

存在する演算子は、 他のプロパティを変えることなく、 matchfix演算子として再宣言することができます。 特に、足し算+のような組み込み演算子が matchfixに宣言されることが可能ですが、 演算子関数は組み込み演算子に関して定義できません。

コマンドmatchfix (ldelimiter, rdelimiter, arg_pos, pos) は、 引数品詞arg_posと結果品詞pos、区切り記号 ldelimiterrdelimiterを宣言します。

演算子宣言に関して、「品詞」は式のタイプを意味します。 3つのタイプが認識されます: それぞれ、代数式、ブーリアン式、任意の種類の式を示す、 expr, clause, any。 Maximaは、 宣言された品詞を実際の式と比較することで、 いくつかの構文法エラーを検知します。

matchfix演算を実行する関数は通常のユーザー定義関数です。 演算子関数は、 関数定義演算子:=defineを使って 普通の方法で定義されます。 引数は、区切り記号の間に書かれるか、 クォートされた文字列としての左区切り記号と括弧の中で続く引数を使って書かれます。 dispfun (ldelimiter)は関数定義を表示します。

唯一の組み込みmatchfix演算子はリスト構成子[ ]です。 括弧( )とダブルクォート" "はmatchfix演算子のように振る舞いますが、 Maximaパーサによってそのようには扱われません。

matchfixは引数を評価します。 matchfixは最初の引数ldelimiterを返します。

例:

区切り記号はほとんど任意の文字列を取り得ます。

(%i1) matchfix ("@@", "~");
(%o1)                          @@
(%i2) @@ a, b, c ~;
(%o2)                      @@a, b, c~
(%i3) matchfix (">>", "<<");
(%o3)                          >>
(%i4) >> a, b, c <<;
(%o4)                      >>a, b, c<<
(%i5) matchfix ("foo", "oof");
(%o5)                          foo
(%i6) foo a, b, c oof;
(%o6)                     fooa, b, coof
(%i7) >> w + foo x, y oof + z << / @@ p, q ~;
                     >>z + foox, yoof + w<<
(%o7)                ----------------------
                            @@p, q~

Matchfix演算子は通常のユーザー定義関数です。

(%i1) matchfix ("!-", "-!");
(%o1)                         "!-"
(%i2) !- x, y -! := x/y - y/x;
                                    x   y
(%o2)                   !-x, y-! := - - -
                                    y   x
(%i3) define (!-x, y-!, x/y - y/x);
                                    x   y
(%o3)                   !-x, y-! := - - -
                                    y   x
(%i4) define ("!-" (x, y), x/y - y/x);
                                    x   y
(%o4)                   !-x, y-! := - - -
                                    y   x
(%i5) dispfun ("!-");
                                    x   y
(%t5)                   !-x, y-! := - - -
                                    y   x

(%o5)                         done
(%i6) !-3, 5-!;
                                16
(%o6)                         - --
                                15
(%i7) "!-" (3, 5);
                                16
(%o7)                         - --
                                15
関数: nary (op)
関数: nary (op, bp, arg_pos, pos)

nary演算子は 任意の数の引数の関数を示すのに使われます。 引数それぞれは、例えば、A+BやA+B+Cように演算子の出現で分離されます。 nary("x")関数は xnary演算子に宣言する構文拡張関数です。 関数は naryであると宣言されるかもしれません。 もし declare(j,nary);が実行されたら、 これは整理器に 例えば、j(j(a,b),j(c,d))j(a, b, c, d)に整理するよう指示します。

Introduction to operatorsも参照してください。

関数: nofix (op)
関数: nofix (op, pos)

nofix演算子は引数のない関数を示すのに使われます。 コマンドにそんな演算子が存在すると、 対応する関数が評価されるだけです。 例えば、Maximaブレイクから抜けるために"exit;"とタイプする時、 "exit"はnofix演算子と似たように振る舞います。 関数 nofix("x")xnofix演算子に宣言する構文拡張関数です。

Introduction to operatorsも参照してください。

関数: postfix (op)
関数: postfix (op, lbp, lpos, pos)

prefix変種のようなpostfix演算子は引数一つの関数を示しますが、 この場合、例えば3!のように、入力文字列の中で引数が演算子に先行します。 postfix("x")関数は xpostfix演算子に宣言する構文拡張関数です。

Introduction to operatorsも参照してください。

関数: prefix (op)
関数: prefix (op, rbp, rpos, pos)

prefix演算子は引数一つの関数であり、 その引数は演算子のすぐ後ろに置かれます。 prefix("x")xprefix演算子に宣言する構文拡張関数です。

Introduction to operatorsも参照してください。


Previous: Assignment operators, Up: Operators   [Contents][Index]