指定された優先順位を持つ新しい演算子を定義したり、 既存の演算子を未定義にしたり、既存の演算子の優先順位を再定義することが可能です。 演算子は単項前置、単項後置、二項中置、n項中置、マッチフィックスか無項でありえます。 「マッチフィックス」は引数を括るシンボルの対を意味し、 「無項」は引数を取らない演算子を意味します。 異なるタイプの演算子の例として、以下があります。
negation - a
factorial a!
exponentiation a^b
addition a + b
list construction [a, b]
(組み込みの無項演算子はありません; そんな演算子の例は、nofixを参照してください。.)
新しい演算子を定義するメカニズムはわかりやすいものです。 関数を演算子として宣言することだけが必要です; 演算子関数は定義されることもされないこともあります。
ユーザー定義の演算子の例は以下の通りです。
明示的な関数コール "dd" (a)は dd aと同値であり、また、
"<-" (a, b)は a <- bと同値であることに注意してください。
この例で、 "dd"と "<-"は未定義です。
(%i1) prefix ("dd");
(%o1) dd
(%i2) dd a;
(%o2) dd a
(%i3) "dd" (a);
(%o3) dd a
(%i4) infix ("<-");
(%o4) <-
(%i5) a <- dd b;
(%o5) a <- dd b
(%i6) "<-" (a, "dd" (b));
(%o6) a <- dd b
新しい演算子を定義するMaxima関数はこの表にまとめられます。 デフォルトの左と右の結合力(それぞれlbpとrbp)を記載します。 (結合力は演算子の優先順位を決めます。 しかしながら、左と右の結合力は異なることがあり、 結合力は優先順位より幾分複雑です。) 演算定義関数のいくつかは追加の引数を取ります; 詳細は関数記述を参照してください。
prefixrbp=180
postfixlbp=180
infixlbp=180, rbp=180
narylbp=180, rbp=180
matchfix(binding power not applicable)
nofix(binding power not applicable)
比較のために、いくつかの組み込み演算子と左右結合力を上げます。
Operator lbp rbp : 180 20 :: 180 20 := 180 20 ::= 180 20 ! 160 !! 160 ^ 140 139 . 130 129 * 120 / 120 120 + 100 100 - 100 134 = 80 80 # 80 80 > 80 80 >= 80 80 < 80 80 <= 80 80 not 70 and 65 or 60 , 10 $ -1 ; -1
removeと killは演算子プロパティをアトムから削除します。
remove ("a", op)は aの演算子プロパティだけを削除します。
kill ("a")は 演算子プロパティを含むaのすべてのロパティを削除します。
演算子名はクォーテーションマークで括らないといけないことに注意してください。
(%i1) infix ("##");
(%o1) ##
(%i2) "##" (a, b) := a^b;
b
(%o2) a ## b := a
(%i3) 5 ## 3;
(%o3) 125
(%i4) remove ("##", op);
(%o4) done
(%i5) 5 ## 3;
Incorrect syntax: # is not a prefix operator
5 ##
^
(%i5) "##" (5, 3);
(%o5) 125
(%i6) infix ("##");
(%o6) ##
(%i7) 5 ## 3;
(%o7) 125
(%i8) kill ("##");
(%o8) done
(%i9) 5 ## 3;
Incorrect syntax: # is not a prefix operator
5 ##
^
(%i9) "##" (5, 3);
(%o9) ##(5, 3)
シンボル + * / ^はそれぞれ、
足し算、かけ算、割り算、べき乗を表します。
これらの演算子の名前は "+" "*" "/" "^"です。
これらは関数や演算子の名前が求められるところで使います。
シンボル +や -はそれぞれ、プラスとマイナスの単項演算子を示し、
それらの名前はそれぞれ "+"と"-"です。
引き算 a - bはMaximaの中では足し算 a + (- b)として表されます。
a + (- b)のような式は引き算として表示されます。
Maximaは "-"を足し算の単項逆元演算子の名前としてのみ認識して、
二項引き算演算子としては認識しません。
Maximaの中では割り算a / bをかけ算a * b^(- 1)として表現します。
a * b^(- 1)のような式は割り算として表示されます。
Maximaは"/"を割り算演算子の名前として認識します。
足し算とかけ算はn項可換演算子です。 割り算とべき乗は二項の非可換演算子です。
Maximaは正準表現を構成するために可換演算子のオペランド(訳注:引数)を並べ替えます。
順序は内部的には orderlesspで決定します。
表示のためには、足し算の順序は ordergreatpで決定し、
かけ算は内部的な順序と同じです。
算術計算は、数リテラル(整数、有理数、通常の浮動小数点、多倍長浮動小数点)上で実行されます。
べき乗を除いて、数に対するすべての算術演算子は数に整理されます。
べき乗は、オペランドが通常の浮動小数点か多倍長浮動小数点の時、もしくは結果が厳密に整数もしくは有理数の時、数に整理されます;
そうでなければ、べき乗は sqrtか他のべき乗に整理されるか、そのまま残されます。
浮動小数点の伝搬が算術計算に適用されます: もしどれか1つでもオペランドが多倍長浮動小数点なら、結果は多倍長浮動小数点です; そうでなければ、もしどれか1つでもオペランドが通常の浮動小数点なら、結果は通常の浮動小数点です; そうでなければオペランドは有理数か整数であり、結果は有理数か整数です。
算術計算は式整理であって、評価ではありません。 従って、クォートされた(しかし整理される)式の中で算術計算は実行されます。
算術演算は、
グローバルフラグ listarithが trueの時
リストに対して要素毎に適用され、
行列に対しては常に要素毎に適用されます。
オペランドの1つがリストか行列であり、もう1つのオペランドが別のタイプの時、
他のオペランドはリストか行列の要素のそれぞれに組み合わされます。
例:
足し算とかけ算は、n項可換演算子です。
Maximaは、正準表現を構成するために、可換演算子のオペランドを並べ替えます。
それらの名前はそれぞれ "+"と "*"です。
(%i1) c + g + d + a + b + e + f;
(%o1) g + f + e + d + c + b + a
(%i2) [op (%), args (%)];
(%o2) [+, [g, f, e, d, c, b, a]]
(%i3) c * g * d * a * b * e * f;
(%o3) a b c d e f g
(%i4) [op (%), args (%)];
(%o4) [*, [a, b, c, d, e, f, g]]
(%i5) apply ("+", [a, 8, x, 2, 9, x, x, a]);
(%o5) 3 x + 2 a + 19
(%i6) apply ("*", [a, 8, x, 2, 9, x, x, a]);
2 3
(%o6) 144 a x
割り算とべき乗は、二項の非可換演算子です。
それらの名前はそれぞれ "/"と "^"です。
(%i1) [a / b, a ^ b];
a b
(%o1) [-, a ]
b
(%i2) [map (op, %), map (args, %)];
(%o2) [[/, ^], [[a, b], [a, b]]]
(%i3) [apply ("/", [a, b]), apply ("^", [a, b])];
a b
(%o3) [-, a ]
b
引き算と割り算は内部的にはそれぞれ、足し算とかけ算を使って表現されます。
(%i1) [inpart (a - b, 0), inpart (a - b, 1), inpart (a - b, 2)];
(%o1) [+, a, - b]
(%i2) [inpart (a / b, 0), inpart (a / b, 1), inpart (a / b, 2)];
1
(%o2) [*, a, -]
b
計算は数リテラルに対して実行されます。 浮動小数点伝搬が適用されます。
(%i1) 17 + b - (1/2)*29 + 11^(2/4);
5
(%o1) b + sqrt(11) + -
2
(%i2) [17 + 29, 17 + 29.0, 17 + 29b0];
(%o2) [46, 46.0, 4.6b1]
算術計算は式整理であって、評価ではありません。
(%i1) simp : false;
(%o1) false
(%i2) '(17 + 29*11/7 - 5^3);
29 11 3
(%o2) 17 + ----- - 5
7
(%i3) simp : true;
(%o3) true
(%i4) '(17 + 29*11/7 - 5^3);
437
(%o4) - ---
7
算術計算は(listarithに依存して)リストや行列に対して要素毎に実行されます。
(%i1) matrix ([a, x], [h, u]) - matrix ([1, 2], [3, 4]);
[ a - 1 x - 2 ]
(%o1) [ ]
[ h - 3 u - 4 ]
(%i2) 5 * matrix ([a, x], [h, u]);
[ 5 a 5 x ]
(%o2) [ ]
[ 5 h 5 u ]
(%i3) listarith : false;
(%o3) false
(%i4) [a, c, m, t] / [1, 7, 2, 9];
[a, c, m, t]
(%o4) ------------
[1, 7, 2, 9]
(%i5) [a, c, m, t] ^ x;
x
(%o5) [a, c, m, t]
(%i6) listarith : true;
(%o6) true
(%i7) [a, c, m, t] / [1, 7, 2, 9];
c m t
(%o7) [a, -, -, -]
7 2 9
(%i8) [a, c, m, t] ^ x;
x x x x
(%o8) [a , c , m , t ]
べき乗演算子。
Maximaは入力の中で **を ^と同じ演算子と認識し、
1次元出力の中では ^として表示し、
また、2次元出力の中では指数を上付き添字として配置します。
fortran関数は、入力が **でも ^でも、
べき乗演算子を **として表示します。
例:
(%i1) is (a**b = a^b);
(%o1) true
(%i2) x**y + x^z;
z y
(%o2) x + x
(%i3) string (x**y + x^z);
(%o3) x^z+x^y
(%i4) fortran (x**y + x^z);
x**z+x**y
(%o4) done
非可換べき乗演算子。
ちょうど可換なかけ算 *に通常のべき乗演算子 ^が対応するように、
^^は非可換かけ算 .に対応するべき乗演算子です。
非可換べき乗演算子は、1次元出力では ^^で表示され、
2次元出力では、指数をかっこ < >で囲まれた上付き添字として置きます。
例:
(%i1) a . a . b . b . b + a * a * a * b * b;
3 2 <2> <3>
(%o1) a b + a . b
(%i2) string (a . a . b . b . b + a * a * a * b * b);
(%o2) a^3*b^2+a^^2 . b^^3
行列(非可換)かけ算のためのドット演算子。
"."をこの意味で用いる時、
例えば A . Bのように両側にスペースを置かなければいけません。
これで浮動小数点の小数点と区別します。
dotや
dot0nscsimp,
dot0simp,
dot1simp,
dotassoc,
dotconstrules,
dotdistrib,
dotexptsimp,
dotident,
dotscrules.
も参照してください。
シンボル < <= >= >はそれぞれ、小なり、以下、以上、大なり、を表します。
これらの演算子の名前は、 "<"、 "<="、 ">="、 ">"です。
それらは関数や演算子の名前が求められるところで使われます。
これらの関係演算子はすべて二項演算子です;
a < b < cのような構成をMaximaは認識しません。
関数 isや maybe、
プログラミング構成子 if, while, unlessが
関係式をブーリアン値に評価します。
そうでなければ、関係式はブーリアン値に評価されたり整理されたりしませんが、
関係式の引数は(評価がクォーテーションによって妨げられないかぎり)評価されます。
関係式が trueもしくは falseに評価できない時、
isや ifの振る舞いは、グローバルフラグ prederrorが決定します。
prederrorが trueの時、 isや ifはエラーをトリガーします。
prederrorが falseの時、
isは unknownを返し、
ifは部分的に評価された条件式を返します。
maybeはいつも、 prederrorが falseであるかのように振る舞い、
whileや unlessはいつも、 prederrorが trueであるかのように振る舞います。
関係演算子はリストやほかの集合上で展開されることはありません。
=や #、 equal、 notequalも参照してください。
例:
いくつかの関数やプログラミング構成子が関係式をブーリアン値に評価します。
(%i1) [x, y, z] : [123, 456, 789];
(%o1) [123, 456, 789]
(%i2) is (x < y);
(%o2) true
(%i3) maybe (y > z);
(%o3) false
(%i4) if x >= z then 1 else 0;
(%o4) 0
(%i5) block ([S], S : 0, for i:1 while i <= 100 do S : S + i,
return (S));
(%o5) 5050
そうでなければ関係式はブーリアン値に評価されたり整理されたりしませんが、 関係式の引数は評価されます。
(%o1) [123, 456, 789] (%i2) [x < y, y <= z, z >= y, y > z]; (%o2) [123 < 456, 456 <= 789, 789 >= 456, 456 > 789] (%i3) map (is, %); (%o3) [true, true, true, false]
論理積演算子。
andは、n項中置演算子です;
オペランドはブーリアン値で、結果もブーリアン値です。
andは、(isのように)1以上のオペランドの評価を強制し、
すべてのオペランドの評価を強制するかもしれません。
オペランドは、出現順に評価されます。
andは、結果を決定するのに必要なだけオペランドを評価します。
もし任意のオペランドがfalseなら、結果はfalseであり、
ほかのオペランドは評価されません。
グローバルフラグprederrorは、
評価されたオペランドがtrueかfalseに決定できない時のandの振る舞いを決定します。
prederrorがtrueの時、andは、エラーメッセージを出力します。
そうでなければ、trueかfalseに評価されないオペランドを受け付け、
結果はブーリアン式になります。
andは可換ではありません:
a and bは、不定のオペランドの扱いのため、b and aと同値ではないかもしれません。
論理否定演算子。
notは、接頭演算子です;
オペランドはブーリアン値で、結果もブーリアン値です。
orは、(isのように)オペランドの評価を強制します。
グローバルフラグprederrorは、
評価されたオペランドがtrueかfalseに決定できない時のnotの振る舞いを決定します。
prederrorがtrueの時、notは、エラーメッセージを出力します。
そうでなければ、trueかfalseに評価されないオペランドを受け付け、
結果はブーリアン式になります。
論理和演算子。
orは、n項中置演算子です;
オペランドはブーリアン値で、結果もブーリアン値です。
orは、(isのように)1以上のオペランドの評価を強制し、
すべてのオペランドの評価を強制するかもしれません。
オペランドは、出現順に評価されます。
andは、結果を決定するのに必要なだけオペランドを評価します。
もし任意のオペランドがtrueなら、結果はtrueであり、
ほかのオペランドは評価されません。
グローバルフラグprederrorは、
評価されたオペランドがtrueかfalseに決定できない時のorの振る舞いを決定します。
prederrorがtrueの時、orは、エラーメッセージを出力します。
そうでなければ、trueかfalseに評価されないオペランドを受け付け、
結果はブーリアン式になります。
orは可換ではありません:
a or bは、不定のオペランドの扱いのため、b or aと同値ではないかもしれません。
構文的等号=の否定を表します。
述語論理式の評価のルールのため
(特に not exprは exprの評価を伴うので)、
not a = bは、 a # bではなく、
is(a # b)と同値です。
例:
(%i1) a = b; (%o1) a = b (%i2) is (a = b); (%o2) false (%i3) a # b; (%o3) a # b (%i4) not a = b; (%o4) true (%i5) is (a # b); (%o5) true (%i6) is (not a = b); (%o6) true
等式演算子。
式a = bは、それ自身、未評価の等式を表します。
等式は成り立つかもしれませんし、成り立たないかもしれません。
未評価の等式は、solveやalgsysや他の関数の引数として用いられます。
関数isは、=をブーリアン値に評価します。
is(a = b)は、aとbが同一のとき、
a = bをtrueに評価します。
すなわち、aとbが同一のアトムであるか、もしくは、それらはアトムではなく、
それらの演算子が同一で、演算子の引数が同一です。
そうでなければ、is(a = b)はfalseに評価されます;
決して、unknownには評価されません。
is(a = b)がtrueの時、
aとbは、同値の式と対照的に、構文法的に等しいと言われます。
同値の式は、is(equal(a, b))がtrueの式です。
式は、同値だが構文法的に等しくないことが起こりえます。
=の否定は、#で表されます。
=と同様、式a # bは、それ自身、評価されません。
is(a # b)は、a # bをtrueもしくはfalseに評価します。
isに加えて、他のいくつかの演算子が=と#をtrueもしくはfalseに評価します。if, and, or, notという演算子です。
述語論理式の評価規則のため
(特に、not exprはexprの評価を起こすため)、
not a = bは、a # bではなく、
is(a # b)と同値になります。
rhsとlhsは、それぞれ、等式、不等式の右辺と左辺を返します。
例:
式a = bは、それ自身、未評価の等式であり、成り立つことも成り立たないこともあります。
(%i1) eq_1 : a * x - 5 * y = 17;
(%o1) a x - 5 y = 17
(%i2) eq_2 : b * x + 3 * y = 29;
(%o2) 3 y + b x = 29
(%i3) solve ([eq_1, eq_2], [x, y]);
196 29 a - 17 b
(%o3) [[x = ---------, y = -----------]]
5 b + 3 a 5 b + 3 a
(%i4) subst (%, [eq_1, eq_2]);
196 a 5 (29 a - 17 b)
(%o4) [--------- - --------------- = 17,
5 b + 3 a 5 b + 3 a
196 b 3 (29 a - 17 b)
--------- + --------------- = 29]
5 b + 3 a 5 b + 3 a
(%i5) ratsimp (%);
(%o5) [17 = 17, 29 = 29]
is(a = b)は、
aとbが構文法的に等しい(すなわち、同一の)時
式は、同値だが構文法的に等しくないことがありえます。
(%i1) a : (x + 1) * (x - 1);
(%o1) (x - 1) (x + 1)
(%i2) b : x^2 - 1;
2
(%o2) x - 1
(%i3) [is (a = b), is (a # b)];
(%o3) [false, true]
(%i4) [is (equal (a, b)), is (notequal (a, b))];
(%o4) [true, false]
いくつかの演算子は、=と#をtrueもしくはfalseに評価します。
(%i1) if expand ((x + y)^2) = x^2 + 2 * x * y + y^2 then FOO else
BAR;
(%o1) FOO
(%i2) eq_3 : 2 * x = 3 * x;
(%o2) 2 x = 3 x
(%i3) eq_4 : exp (2) = %e^2;
2 2
(%o3) %e = %e
(%i4) [eq_3 and eq_4, eq_3 or eq_4, not eq_3];
(%o4) [false, true, true]
not exprはexprの評価をするので、
not a = bは、is(a # b)と同値です。
(%i1) [2 * x # 3 * x, not (2 * x = 3 * x)]; (%o1) [2 x # 3 x, true] (%i2) is (2 * x # 3 * x); (%o2) true
割り当て演算子。
左辺が(添字のない)単純変数の時、 :は右辺を評価し、その値を左辺に関連づけます。
左辺がリストや行列、宣言されたMaxima配列、Lisp配列の添字指定された要素の時、 右辺がその要素に割り当てられます。 添字は存在している要素を示していなければなりません; 先に列挙した対象は、存在していない要素を名付けることで拡張することはできません。
左辺が未宣言のMaxima配列の添字指定された要素の時、 もし既に存在しているなら、右辺はその要素に割り当てられ、 もしまだ存在していなければ新しい要素が確保されます。
左辺が単純変数や添字あり変数のリストの時、 右辺はリストに評価されなければなりません。 そして、右辺の要素が左辺の要素に平行に割り当てられます。
killやremvalueも参照してください。
それらは左辺とその値の関連をアンドゥします。
例:
単純変数への割り当て
(%i1) a; (%o1) a (%i2) a : 123; (%o2) 123 (%i3) a; (%o3) 123
リストの要素への割り当て
(%i1) b : [1, 2, 3]; (%o1) [1, 2, 3] (%i2) b[3] : 456; (%o2) 456 (%i3) b; (%o3) [1, 2, 456]
割り当ては未宣言配列を生成する。
(%i1) c[99] : 789; (%o1) 789 (%i2) c[99]; (%o2) 789 (%i3) c; (%o3) c (%i4) arrayinfo (c); (%o4) [hashed, 1, [99]] (%i5) listarray (c); (%o5) [789]
多重割り当て
(%i1) [a, b, c] : [45, 67, 89]; (%o1) [45, 67, 89] (%i2) a; (%o2) 45 (%i3) b; (%o3) 67 (%i4) c; (%o4) 89
多重割り当ては平行に実行されます。
この例ではaとbの値が置換されます。
(%i1) [a, b] : [33, 55]; (%o1) [33, 55] (%i2) [a, b] : [b, a]; (%o2) [55, 33] (%i3) a; (%o3) 55 (%i4) b; (%o4) 33
割り当て演算子。
::は、::は右辺はもちろん左辺も評価することを除いて、:と同じです。
例:
(%i1) x : 'foo; (%o1) foo (%i2) x :: 123; (%o2) 123 (%i3) foo; (%o3) 123 (%i4) x : '[a, b, c]; (%o4) [a, b, c] (%i5) x :: [11, 22, 33]; (%o5) [11, 22, 33] (%i6) a; (%o6) 11 (%i7) b; (%o7) 22 (%i8) c; (%o8) 33
マクロ関数定義の演算子。
::=は、引数をクォートする関数(歴史的理由によりマクロと呼ばれる)を定義します。
そして、それが返す式(マクロ展開と呼ばれる)はマクロが呼ばれた文脈の中で評価されます。
それ以外はマクロ関数は通常の関数と同じです。
macroexpandは(評価せずに)マクロ展開を返します。
fooがマクロ関数の時、
macroexpand (foo (x))に続けて ``%を実行すると、
それは foo (x)と同値です。
::=は、新しいマクロ関数の名前をグローバルリスト macrosに追加します。
killや remove, remfunctionは、マクロ関数定義をアンバインドし、
macrosから名前を削除します。
fundefや dispfunはそれぞれマクロ関数定義を返し、
それをラベルに割り当てます。
評価対象となる式を構成するために、
マクロ関数は一般的にbuildq, splice式を含みます。
例
マクロ関数は引数をクォートします。
だから、メッセージ(1)は y - zの値ではなく、 y - zを示します。
マクロ展開(クォートされた式 '(print ("(2) x is equal to", x))は、
マクロが呼ばれた文脈(表示メッセージ(2))の中で評価されます。
(%i1) x: %pi$
(%i2) y: 1234$
(%i3) z: 1729 * w$
(%i4) printq1 (x) ::= block (print ("(1) x is equal to", x),
'(print ("(2) x is equal to", x)))$
(%i5) printq1 (y - z);
(1) x is equal to y - z
(2) x is equal to %pi
(%o5) %pi
通常の関数は引数を評価します。だから、メッセージ(1)は y - zの値を示します。
戻り値は評価されず、従って、メッセージ(2)は ``%で陽に評価されるまで出力されません。
(%i1) x: %pi$
(%i2) y: 1234$
(%i3) z: 1729 * w$
(%i4) printe1 (x) := block (print ("(1) x is equal to", x),
'(print ("(2) x is equal to", x)))$
(%i5) printe1 (y - z);
(1) x is equal to 1234 - 1729 w
(%o5) print((2) x is equal to, x)
(%i6) ''%;
(2) x is equal to %pi
(%o6) %pi
macroexpandはマクロ展開を返します。
fooがマクロ関数の時、
macroexpand (foo (x))の後 ``%を実行すると、foo (x)と同値です。
(%i1) x: %pi$
(%i2) y: 1234$
(%i3) z: 1729 * w$
(%i4) g (x) ::= buildq ([x], print ("x is equal to", x))$
(%i5) macroexpand (g (y - z));
(%o5) print(x is equal to, y - z)
(%i6) ''%;
x is equal to 1234 - 1729 w
(%o6) 1234 - 1729 w
(%i7) g (y - z);
x is equal to 1234 - 1729 w
(%o7) 1234 - 1729 w
関数定義の演算子。
f(x_1, .., x_n) := exprは、
引数がx_1, ..., x_nで関数本体がexprの、fという名前の関数を定義します。
:=は(クォートクォート``で陽に評価されない限り)関数本体は評価しません。
定義される関数は(引数をかっこでくくる)通常のMaxima関数か、(引数をかぎかっこでくくる)配列関数です。
最後の引数x_nが要素1つのリストの時、:=で定義された関数は可変の数の引数をとります。
実際の引数は、形式的な引数x_1, …, x_(n - 1)に一対一に割り当てられ、
さらに引数があれば、x_nにリストとして割り当てられます。
関数定義すべては、同じ名前空間を使います;
別の関数gの中で関数fを定義することは、fのスコープをgに限定しません。
しかし、local(f)は、関数fの定義をlocalが現れたブロックや他の合成式内に限定します。
もしある形式引数x_kがクォートされたシンボルなら、:=で定義された関数は対応する実際の引数を評価しません。
それ以外の場合、実際の引数はすべて評価されます。
例:
:=は(クォートクォートで陽に評価されない限り)関数本体を評価しません。
(%i1) expr : cos(y) - sin(x); (%o1) cos(y) - sin(x) (%i2) F1 (x, y) := expr; (%o2) F1(x, y) := expr (%i3) F1 (a, b); (%o3) cos(y) - sin(x) (%i4) F2 (x, y) := ''expr; (%o4) F2(x, y) := cos(y) - sin(x) (%i5) F2 (a, b); (%o5) cos(b) - sin(a)
:=で定義された関数は、通常のMaxima関数か、配列関数です。
(%i1) G1 (x, y) := x.y - y.x;
(%o1) G1(x, y) := x . y - y . x
(%i2) G2 [x, y] := x.y - y.x;
(%o2) G2 := x . y - y . x
x, y
最後の引数x_nが要素1つのリストの時、
:=で定義された関数は、可変の数の引数を取ります。
(%i1) H ([L]) := apply ("+", L);
(%o1) H([L]) := apply("+", L)
(%i2) H (a, b, c);
(%o2) c + b + a
localはローカル関数定義を可能にします。
(%i1) foo (x) := 1 - x; (%o1) foo(x) := 1 - x (%i2) foo (100); (%o2) - 99 (%i3) block (local (foo), foo (x) := 2 * x, foo (100)); (%o3) 200 (%i4) foo (100); (%o4) - 99
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のインスタンスが 式の中で右にある他の演算子の前に評価されることを示します。 このように、より大きなlbpはopを右結合にし、 より大きなrbpはopを左結合にします。 もしlbpがrbpと等しいなら、 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)
より大きなlbpはopを右結合にし、 より大きなrbpはopを左結合にします。
(%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
左と右の区切り記号ldelimiterとrdelimiterを持つ matchfix演算子を宣言します 区切り記号は文字列として指定されます。
"matchfix"演算子は、
任意の数の引数の関数で、引数は左と右の区切り記号をマッチする間で現れます。
パーサがオペランドや他の式や演算子から区切り記号を区別できる限り
区切り記号は任意の文字列を取り得ます。
実際には、これは、%, ,, $, ;のような
パースできない区切り記号を除外し、空白を持つ区切り記号を分離することを要求するかもしれません。
右区切り記号は、左区切り記号と同じかもしれませんし、違うかもしれません。
左区切り記号は、たった1つの右区切り記号と関連づけられることができます; 2つの異なるmatchfix演算子は同じ左区切り記号を持つことはできません。
存在する演算子は、
他のプロパティを変えることなく、
matchfix演算子として再宣言することができます。
特に、足し算+のような組み込み演算子が
matchfixに宣言されることが可能ですが、
演算子関数は組み込み演算子に関して定義できません。
コマンドmatchfix (ldelimiter, rdelimiter, arg_pos,
pos) は、
引数品詞arg_posと結果品詞pos、区切り記号
ldelimiterとrdelimiterを宣言します。
演算子宣言に関して、「品詞」は式のタイプを意味します。
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演算子は
任意の数の引数の関数を示すのに使われます。
引数それぞれは、例えば、A+BやA+B+Cように演算子の出現で分離されます。
nary("x")関数は
xを nary演算子に宣言する構文拡張関数です。
関数は naryであると宣言されるかもしれません。
もし declare(j,nary);が実行されたら、
これは整理器に
例えば、j(j(a,b),j(c,d))を j(a, b, c, d)に整理するよう指示します。
Introduction to operatorsも参照してください。
nofix演算子は引数のない関数を示すのに使われます。
コマンドにそんな演算子が存在すると、
対応する関数が評価されるだけです。
例えば、Maximaブレイクから抜けるために"exit;"とタイプする時、
"exit"はnofix演算子と似たように振る舞います。
関数 nofix("x")は
xを nofix演算子に宣言する構文拡張関数です。
Introduction to operatorsも参照してください。
prefix変種のようなpostfix演算子は引数一つの関数を示しますが、
この場合、例えば3!のように、入力文字列の中で引数が演算子に先行します。
postfix("x")関数は xをpostfix演算子に宣言する構文拡張関数です。
Introduction to operatorsも参照してください。
prefix演算子は引数一つの関数であり、
その引数は演算子のすぐ後ろに置かれます。
prefix("x")は xをprefix演算子に宣言する構文拡張関数です。
Introduction to operatorsも参照してください。