Previous: Macros, Up: Function Definition [Contents][Index]
F(x_1, ..., x_n)を構成、評価します。
applyは、配列関数を通常の関数と区別しようとはしません;
Fが配列関数の名前の時、applyはF(...)(カギ括弧の代わりに括弧での関数コール)を評価します。
arrayapplyは、この場合、カギ括弧ありで関数コールを評価します。
例:
applyは、引数を評価します。
この例では、minがLの値に適用されます。
(%i1) L : [1, 5, -10.2, 4, 3]; (%o1) [1, 5, - 10.2, 4, 3] (%i2) apply (min, L); (%o2) - 10.2
applyは、たとえ関数Fが引数をクォートする場合でも、引数を評価します。
(%i1) F (x) := x / 1729;
x
(%o1) F(x) := ----
1729
(%i2) fname : F;
(%o2) F
(%i3) dispfun (F);
x
(%t3) F(x) := ----
1729
(%o3) [%t3]
(%i4) dispfun (fname);
fname is not the name of a user function.
-- an error. Quitting. To debug this try debugmode(true);
(%i5) apply (dispfun, [fname]);
x
(%t5) F(x) := ----
1729
(%o5) [%t5]
applyは関数名Fを評価します。
シングルクオート'は評価を無効にします。
demoivreはグローバル変数の名前であり、また、関数でもあります。
(%i1) demoivre;
(%o1) false
(%i2) demoivre (exp (%i * x));
(%o2) %i sin(x) + cos(x)
(%i3) apply (demoivre, [exp (%i * x)]);
demoivre evaluates to false
Improper name or value in functional position.
-- an error. Quitting. To debug this try debugmode(true);
(%i4) apply ('demoivre, [exp (%i * x)]);
(%o4) %i sin(x) + cos(x)
blockはexpr_1, ..., expr_nを順に評価し、評価された最後の式の値を返します。
順序はgo, throw, return関数によって変更することができます。
最後の式は、returnもしくはthrowを含む式が評価されないなら、expr_nです。
いくつかの変数v_1, ..., v_mがブロックにローカルに宣言できます;
これらは同じ名前のグローバル変数と区別されます。
変数がローカルに宣言されないなら、リストは省略できます。
ブロック内では、v_1, ..., v_m以外の変数はグローバル変数です。
blockは(存在するなら)変数v_1, ..., v_mの現在の値を保存し、
変数がそれ自身に評価されるよう変数のバインドを解除します。
ローカル変数はブロック内部で任意の値にバインドできますが、
ブロックが終了するとき保存された値が戻され、
ブロック内で割り当てられた値は失われます。
block内部の宣言local(v_1, ..., v_m)は
シンボルv_1, ..., v_mに関連付けられた性質を保存し、
他の式を評価する前に、性質を取り除き、ブロック終了時に元に戻します。
いくつかの宣言は、:=、array, dependencies, atvalue, matchdeclare,
atomgrad, constant, nonscalarその他を含むシンボルの性質として実装されます。
localの効果は、ブロック内部のみで有効な宣言を作ります;
そうでなければ、ブロック内部の宣言は実際にグローバル宣言となります。
blockは他のblock内部でも現れます。
ローカル変数が、新しいブロックが評価されるたびに確立されます。
ローカル変数は、内包するブロックではグローバルです。
ブロックの中で、変数がローカルでないなら、その値は内包するブロックによって割り当てられた最新の値です。
そうでなければ、グローバル環境の変数の値になります。
このポリシーは「動的スコープ」の普通の理解と一致します。
ブロックの値は、最後の文もしくはブロックから陽に終了するのに使われる関数functionの引数の値です。
関数goは、goの引数でタグされたブロックの文に制御を移すのに使われます。
例えば、block ([x], x:1, loop, x: x+1, ..., go(loop), ...)。
goの引数はブロック内部に現れるタグの名前でなければなりません。
goを含んだブロック以外のブロック内部のタグへ飛ぶのにgoを使うことはできません。
ブロックは、典型的な場合、関数定義の右辺に現れますが、他の場所でも使うことができます。
expr_1, ..., expr_nを評価し、印字し、それから
ユーザーが環境を検査し変更できるところでMaximaブレイクを引き起こします。
exit;をタイプすると、計算が再開されます。
expr_1, ..., expr_nを1つずつ評価します;
もしどれかが形式throw (arg)の式の評価に至るなら、
catchの値はthrow (arg)の値であり、もう式は評価されません。
これの「非局所的リターン」は
入れ子の任意の深さを通過して、throwを含む最も近いcatchに飛びます。
もしthrowを含むcatchがないなら、
エラーメッセージが印字されます。
もし引数の評価が
いかなるthrowの評価にも至らないなら、
catchの値はexpr_nの値です。
(%i1) lambda ([x], if x < 0 then throw(x) else f(x))$
(%i2) g(l) := catch (map (''%, l))$
(%i3) g ([1, 2, 3, 7]);
(%o3) [f(1), f(2), f(3), f(7)]
(%i4) g ([1, 2, -3, 7]);
(%o4) - 3
もしlが非負数だけから成るなら、
lの要素それぞれのfのリストを返します;
そうでなければ、gは "catches" the
first negative element of
lの最初の負の要素を「キャッチ」して、それを「スロー」します。
Maxima関数をLispに翻訳し、翻訳したコードをファイルfilenameに書き込みます。
compfile(filename, f_1, ..., f_n)は
指定された関数を翻訳します。
compfile (filename, functions)と
compfile (filename, all)はユーザー定義関数をすべて翻訳します。
Lisp翻訳は評価されず、出力ファイルはLispコンパイラによって処理もされません。
translateはLisp翻訳を生成し評価します。
compile_fileはMaximaをLispに翻訳し、Lispコンパイラを実行します。
translate, translate_file, compile_fileも参照してください。
Maxima関数f_1, ..., f_nをLispに翻訳し、
Lisp翻訳を評価し、
翻訳された関数それぞれについてLisp関数COMPILEをコールします。
compileは、コンパイルされた関数名のリストを返します。
compile (all)やcompile (functions)は、
ユーザー定義関数すべてをコンパイルします。
compileは引数をクォートします;
クォートクォート演算子''はクォートに優先します。
引数x_1, …, x_nを持ち、
exprの中身を持つfという名前の関数を定義します。
defineは、いつも(陽にクオートされていない限り)、2番目の引数を評価します。
定義された関数は、(かっこでくくられた引数を持つ)通常のMaxima関数
もしくは(カギ括弧でくくられた引数を持つ)配列関数です。
最後の関数の引数x_nが要素1つのリストの時、
defineによって定義される関数は、可変な数の引数を受け入れます。
実際の引数は、形式的な引数, x_1, ..., x_(n - 1)に1対1に割り当てられます。
実際の引数がさらに存在するならx_nにリストとして割り当てられます。
defineの最初の引数がf(x_1, ..., x_n)もしくは
f[x_1, ..., x_n]の形の式の時、
関数の引数は評価されますが、既にその名前の関数や変数があったとしてもfは評価されません。
最初の引数が演算子funmakeもしくはarraymake, evを伴う式の時、
最初の引数は評価されます;これは、本体だけでなく、関数名が計算されることを許します。
すべての関数定義は同じ名前空間で現れます;
関数gの中で関数fを定義することは、fのスコープをgに自動的に限定することにはなりません。
しかしながら、local(f)は、関数fの定義を、
localが現れたブロックや他の合成式内部でのみ有効とします。
もしある形式的な引数x_kが(評価の後)クォートされたシンボルならば、
defineによって定義される関数は、対応する実際の引数を評価しません。
そうでければ、すべての実際の引数は評価されます。
:=や::=も参照してください。
例:
defineは、(陽にクォートされない限り)いつも二番目の引数を評価します
(%i1) expr : cos(y) - sin(x); (%o1) cos(y) - sin(x) (%i2) define (F1 (x, y), expr); (%o2) F1(x, y) := cos(y) - sin(x) (%i3) F1 (a, b); (%o3) cos(b) - sin(a) (%i4) F2 (x, y) := expr; (%o4) F2(x, y) := expr (%i5) F2 (a, b); (%o5) cos(y) - sin(x)
defineが定義する関数は、通常のMaxima関数も配列関数も取り得ます。
(%i1) define (G1 (x, y), x.y - y.x);
(%o1) G1(x, y) := x . y - y . x
(%i2) define (G2 [x, y], x.y - y.x);
(%o2) G2 := x . y - y . x
x, y
最後の、または唯一の引数x_nが1要素のリストの時、
defineが定義した関数は可変の数の引数を受け付けます。
(%i1) define (H ([L]), '(apply ("+", L)));
(%o1) H([L]) := apply("+", L)
(%i2) H (a, b, c);
(%o2) c + b + a
最初の引数が
演算子funmake, arraymake, またはevを含む式なら、
最初の引数は評価されます。
(%i1) [F : I, u : x];
(%o1) [I, x]
(%i2) funmake (F, [u]);
(%o2) I(x)
(%i3) define (funmake (F, [u]), cos(u) + 1);
(%o3) I(x) := cos(x) + 1
(%i4) define (arraymake (F, [u]), cos(u) + 1);
(%o4) I := cos(x) + 1
x
(%i5) define (foo (x, y), bar (y, x));
(%o5) foo(x, y) := bar(y, x)
(%i6) define (ev (foo (x, y)), sin(x) - cos(y));
(%o6) bar(y, x) := sin(x) - cos(y)
グローバル変数をMaxima環境に導入します。
define_variableは、ユーザーが書いたパッケージで役に立ちます。
パッケージはしばしば翻訳されたりコンパイルされたりします。
define_variableは以下のステップを実行します:
mode_declare (name, mode)は、
nameのモードを翻訳器に宣言します。
可能なモードのリストについては、mode_declareを参照してください。
declare (name, special)はそれをspecialと宣言します。
value_checkプロパティは、
define_variableを介して
any以外のモードに定義された任意の変数に割り当てられることができます。
value_checkプロパティは、1変数のラムダ式または関数名です。
それは値を変数に割り当てようとする時にコールされます。
value_check関数の引数は期待値です。
define_variableはdefault_valueを評価し、
nameとmodeをクォートします。
define_variableはnameの現在値を返します。
それは、もしnameがそこでバインドされてないならdefault_valueで
そうでないならnameの以前の値です。
例:
fooはブーリアン変数で、初期値trueを持ちます。
(%i1) define_variable (foo, true, boolean); (%o1) true (%i2) foo; (%o2) true (%i3) foo: false; (%o3) false (%i4) foo: %pi; Error: foo was declared mode boolean, has value: %pi -- an error. Quitting. To debug this try debugmode(true); (%i5) foo; (%o5) false
barは整数変数で、素数でなければいけません。
(%i1) define_variable (bar, 2, integer);
(%o1) 2
(%i2) qput (bar, prime_test, value_check);
(%o2) prime_test
(%i3) prime_test (y) := if not primep(y) then
error (y, "is not prime.");
(%o3) prime_test(y) := if not primep(y)
then error(y, "is not prime.")
(%i4) bar: 1439;
(%o4) 1439
(%i5) bar: 1440;
1440 is not prime.
#0: prime_test(y=1440)
-- an error. Quitting. To debug this try debugmode(true);
(%i6) bar;
(%o6) 1439
baz_quuxは、値を割り当てられない変数です。
モードany_checkはanyのようですが、
any_checkはvalue_checkメカニズムを可能にしますが、
anyはそうしません。
(%i1) define_variable (baz_quux, 'baz_quux, any_check);
(%o1) baz_quux
(%i2) F: lambda ([y], if y # 'baz_quux then
error ("Cannot assign to `baz_quux'."));
(%o2) lambda([y], if y # 'baz_quux
then error(Cannot assign to `baz_quux'.))
(%i3) qput (baz_quux, ''F, value_check);
(%o3) lambda([y], if y # 'baz_quux
then error(Cannot assign to `baz_quux'.))
(%i4) baz_quux: 'baz_quux;
(%o4) baz_quux
(%i5) baz_quux: sqrt(2);
Cannot assign to `baz_quux'.
#0: lambda([y],if y # 'baz_quux then
error("Cannot assign to `baz_quux'."))(y=sqrt(2))
-- an error. Quitting. To debug this try debugmode(true);
(%i6) baz_quux;
(%o6) baz_quux
ユーザー定義関数f_1, ..., f_nの定義を表示します。
引数それぞれは、(::=で定義された)マクロ名、
(:=やdefineで定義された)通常の関数、
(:=ydefineで定義された、しかし引数をカギ括弧[ ]でくくった)
配列関数、
(:=ydefineで定義された、しかしいくつかの引数をカギ括弧[ ]で、他の引数を括弧( )でくくった)添字付き関数、
特別な添字の値で選択された添字付き関数の族の1つ、
定数添字で定義された添字付き関数、
のいずれかを取り得ます。
dispfun (all)は、
functions, arrays, macrosリストで与えられた中で、
定数添字で定義された添字付き関数を除いたユーザー定義関数すべてを表示します。
dispfunは
表示された関数それぞれのために
(%t1, %t2, など)
中間式ラベルを生成し、関数定義をラベルに割り当てます。
対照的に、fundefは関数定義を返します。
dispfunは引数をクォートします;
クォートクォート演算子''はクォートに優先します。
dispfunは表示された関数に対応する中間式ラベルのリストを返します。
例:
(%i1) m(x, y) ::= x^(-y);
- y
(%o1) m(x, y) ::= x
(%i2) f(x, y) := x^(-y);
- y
(%o2) f(x, y) := x
(%i3) g[x, y] := x^(-y);
- y
(%o3) g := x
x, y
(%i4) h[x](y) := x^(-y);
- y
(%o4) h (y) := x
x
(%i5) i[8](y) := 8^(-y);
- y
(%o5) i (y) := 8
8
(%i6) dispfun (m, f, g, h, h[5], h[10], i[8]);
- y
(%t6) m(x, y) ::= x
- y (%t7) f(x, y) := x
- y
(%t8) g := x
x, y
- y
(%t9) h (y) := x
x
1
(%t10) h (y) := --
5 y
5
1
(%t11) h (y) := ---
10 y
10
- y
(%t12) i (y) := 8
8
(%o12) [%t6, %t7, %t8, %t9, %t10, %t11, %t12]
(%i12) ''%;
- y - y - y
(%o12) [m(x, y) ::= x , f(x, y) := x , g := x ,
x, y
- y 1 1 - y
h (y) := x , h (y) := --, h (y) := ---, i (y) := 8 ]
x 5 y 10 y 8
5 10
mapと似ていますが、fullmapは、主演算子が同じでなくなるまで、
部分式すべてに再帰的にマッピングを続けます。
fullmapは、ある行列操作のための整理に使われています;
このように、Maximaは時々、たとえfullmapがユーザーに陽にコールされなくても、
fullmapに関係したエラーメッセージを生成します。
例:
(%i1) a + b * c; (%o1) b c + a (%i2) fullmap (g, %); (%o2) g(b) g(c) + g(a) (%i3) map (g, %th(2)); (%o3) g(b c) + g(a)
fullmapに似ていますが、fullmaplはリストや行列にのみマップします。
例:
(%i1) fullmapl ("+", [3, [4, 5]], [[a, 1], [0, -1.5]]);
(%o1) [[a + 3, 4], [4, 3.5]]
デフォルト値: []
functionsは、現在のセッションでの通常のMaxima関数のリストです。
通常の関数は、defineや:=で構成された関数であり、
括弧()でコールされます。
関数はMaximaプロンプトで定義することができ、また、
loadやbatchがロードするMaximaファイルの中で定義することができます。
(例えばF[x]のように、カギ括弧でコールされる)配列関数と
(例えばF[x](y)のように、カギ括弧と括弧でコールされる)添字付き関数は、
functionsではなくグローバル変数arraysにリストされます。
Lisp関数はどのリストにも保持されません。
例:
(%i1) F_1 (x) := x - 100;
(%o1) F_1(x) := x - 100
(%i2) F_2 (x, y) := x / y;
x
(%o2) F_2(x, y) := -
y
(%i3) define (F_3 (x), sqrt (x));
(%o3) F_3(x) := sqrt(x)
(%i4) G_1 [x] := x - 100;
(%o4) G_1 := x - 100
x
(%i5) G_2 [x, y] := x / y;
x
(%o5) G_2 := -
x, y y
(%i6) define (G_3 [x], sqrt (x));
(%o6) G_3 := sqrt(x)
x
(%i7) H_1 [x] (y) := x^y;
y
(%o7) H_1 (y) := x
x
(%i8) functions;
(%o8) [F_1(x), F_2(x, y), F_3(x)]
(%i9) arrays;
(%o9) [G_1, G_2, G_3, H_1]
関数fの定義を返します。
引数は、(::=で定義された)マクロの名前か、
(:=もしくはdefineで定義された)通常の関数か、
(:=やdefineで定義され、引数がカギ括弧でくくられた)配列関数か、
(:=やdefineで定義され、いくつかの引数がカギ括弧でくくられ、残りがかっこでくくられた)添字関数か、
特別な添字の値によって選択された添字関数族の1つか、一定の添字で定義された添字関数です。
fundefは引数をクォートします;
クォートクォート演算子''はクォートに優先します。
fundef (f)はfの定義を返します。
対照的に、dispfun (f)は中間式ラベルを生成し、ラベルに定義を割り当てます。
式F(arg_1, ..., arg_n)を返します。
戻り値は整理されますが、評価されません。
だから関数Fはたとえ存在してもコールされません。
funmakeは配列関数と通常の関数を区別しようとしません;
Fが配列関数名の時、
funmakeはF(...)を返します
(すなわち、カギ括弧の代わりに括弧での関数コール)。
arraymakeは、この場合,カギ括弧での関数コールを返します。
funmakeは引数を評価します。
例:
通常のMaxima関数に適用されたfunmake。
(%i1) F (x, y) := y^2 - x^2;
2 2
(%o1) F(x, y) := y - x
(%i2) funmake (F, [a + 1, b + 1]);
(%o2) F(a + 1, b + 1)
(%i3) ''%;
2 2
(%o3) (b + 1) - (a + 1)
マクロに適用されたfunmake。
(%i1) G (x) ::= (x - 1)/2;
x - 1
(%o1) G(x) ::= -----
2
(%i2) funmake (G, [u]);
(%o2) G(u)
(%i3) ''%;
u - 1
(%o3) -----
2
添字付き関数に適用されたfunmake。
(%i1) H [a] (x) := (x - 1)^a;
a
(%o1) H (x) := (x - 1)
a
(%i2) funmake (H [n], [%e]);
n
(%o2) lambda([x], (x - 1) )(%e)
(%i3) ''%;
n
(%o3) (%e - 1)
(%i4) funmake ('(H [n]), [%e]);
(%o4) H (%e)
n
(%i5) ''%;
n
(%o5) (%e - 1)
いかなる種類の関数にも定義されていないシンボルへ適用された
funmake
(%i1) funmake (A, [u]); (%o1) A(u) (%i2) ''%; (%o2) A(u)
funmakeは引数を評価しますが、戻り値を評価しません。
(%i1) det(a,b,c) := b^2 -4*a*c;
2
(%o1) det(a, b, c) := b - 4 a c
(%i2) (x : 8, y : 10, z : 12);
(%o2) 12
(%i3) f : det;
(%o3) det
(%i4) funmake (f, [x, y, z]);
(%o4) det(8, 10, 12)
(%i5) ''%;
(%o5) - 284
Maximaはfunmakeの戻り値を整理します。
(%i1) funmake (sin, [%pi / 2]); (%o1) 1
ラムダ式 (すなわち、匿名関数)を定義し返します。 関数は要求された引数x_1, ..., x_mを持ち、 また、オプション引数Lを持つかもしれません。オプション引数は関数本体の中にリストとして現れます。 関数の戻り値はexpr_nです。 ラムダ式は変数に割り当てることができ、通常の関数のように評価できます。 ラムダ式は関数名が期待されるいくつかのコンテキストで現れるかもしれません。
関数が評価される時、
バインドされていないローカル変数x_1, ..., x_mが生成されます。
lambdaは
blockの中や別のlambdaの中で現れるかもしれません;
ローカル変数は、別のblockやlambdaが評価される度に毎回確立されます。
ローカル変数は内包するblockやlambdaにはグローバルのように見えます。
もし変数がローカルでないなら、
その値は、(もし割り当てられたなら)内包するblockやlambdaで直近に割り当てられた値です。
そうでなければ、グローバル環境での変数の値です。
このポリシーは「動的スコープ」の普通の理解と一致するかもしれません。
ローカル変数が確立された後、
expr_1からexpr_nまでが順に評価されます。
特殊変数%%―直前の式の値を表します―が認識されます。
throwとcatchも式のリストの中に現れるかもしれません。
blockで囲まれない限り
returnはラムダ式の中には現れません。
blockで囲まれた場合、
ブロックがたまたま expr_nに至るということでない限り、
returnはラムダ式の戻り値ではなくブロックの戻り値を定義します。
同様に、goは、blockで囲まれない限りラムダ式の中に現れません。
lambdaは引数をクォートします;
クォートクォート演算子''はクォートに優先します。
例:
(%i1) f: lambda ([x], x^2);
2
(%o1) lambda([x], x )
(%i2) f(a);
2
(%o2) a
(%i3) lambda ([x], x^2) (a);
2
(%o3) a
(%i4) apply (lambda ([x], x^2), [a]);
2
(%o4) a
(%i5) map (lambda ([x], x^2), [a, b, c, d, e]);
2 2 2 2 2
(%o5) [a , b , c , d , e ]
''のようにある方法で強制されない限り、
グローバル変数はラムダ式が評価される時評価されます。
(%i6) a: %pi$
(%i7) b: %e$
(%i8) g: lambda ([a], a*b);
(%o8) lambda([a], a b)
(%i9) b: %gamma$
(%i10) g(1/2);
%gamma
(%o10) ------
2
(%i11) g2: lambda ([a], a*''b);
(%o11) lambda([a], a %gamma)
(%i12) b: %e$
(%i13) g2(1/2);
%gamma
(%o13) ------
2
(%i14) h: lambda ([a, b], h2: lambda ([a], a*b), h2(1/2));
1
(%o14) lambda([a, b], h2 : lambda([a], a b), h2(-))
2
(%i15) h(%pi, %gamma);
%gamma
(%o15) ------
2
lambdaは引数をクォートするので、
以下のラムダ式iは
"aを掛ける"関数を定義しません。
以下のラムダ式i2のように、
そんな関数はbuildqを介して定義することができます。
(%i16) i: lambda ([a], lambda ([x], a*x));
(%o16) lambda([a], lambda([x], a x))
(%i17) i(1/2);
(%o17) lambda([x], a x)
(%i18) i2: lambda([a], buildq([a: a], lambda([x], a*x)));
(%o18) lambda([a], buildq([a : a], lambda([x], a x)))
(%i19) i2(1/2);
x
(%o19) lambda([x], -)
2
(%i20) i2(1/2)(%pi);
%pi
(%o20) ---
2
[L]で指定されます。
引数は関数本体の中にリストとして現れます。
(%i1) f : lambda ([aa, bb, [cc]], aa * cc + bb);
(%o1) lambda([aa, bb, [cc]], aa cc + bb)
(%i2) f (foo, %i, 17, 29, 256);
(%o2) [17 foo + %i, 29 foo + %i, 256 foo + %i]
(%i3) g : lambda ([[aa]], apply ("+", aa));
(%o3) lambda([[aa]], apply(+, aa))
(%i4) g (17, 29, x, y, z, %e);
(%o4) z + y + x + %e + 46
シンボルv_1, ..., v_nに関連付けられた性質を保存し、
他の式を評価する前にすべての性質を取り除き、
localが現れたブロックや他の合成式の終了時に保存した性質を元に戻します。
いくつかの宣言は、:=、array, dependencies, atvalue, matchdeclare,
atomgrad, constant, nonscalarその他を含むシンボルの性質として実装されます。
localの効果は、ブロック内部のみで有効な宣言を作ります;
そうでなければ、ブロック内部の宣言は実際にグローバル宣言となります。
localは、blockや関数定義の本体やlambda式の中に現れます。
それぞれの中で1カ所だけ許されます。
localは引数をクォートします。
localはdoneを返します。
例:
ローカル関数定義。
(%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
デフォルト値: false
macroexpansionは
マクロ関数コールを
マクロ関数の展開(すなわち戻り値)で
置き換えるかどうかを制御します。
展開を記憶する代価で、置き換えは次の式評価をスピードアップするかもしれません。
falseマクロ関数コールをマクロ関数の展開で置き換えられません。
expandマクロ関数コールが初めて評価された時、展開が記憶されます。
展開は次のコール時に再計算されません;
(printやグローバル変数への割り当てのような)いかなる副作用も
最初にマクロ関数コールが評価された時だけ起こります。
式の中の展開は、同じマクロ関数コールを持つ他の式に影響を与えません。
displaceマクロ関数コールが初めて評価された時、展開でコールを置き換え、
マクロ関数がコールされた式を変更します。
展開は次のコールで再計算されません;
(printやグローバル変数への割り当てのような)いかなる副作用も
最初にマクロ関数コールが評価された時だけ起こります。
式の中の展開は、同じマクロ関数コールを持つ他の式に影響を与えません。
例
macroexpansionがfalseの時、
コールする式が評価される時毎回マクロ関数がコールされ、
コールする式は変更されません。
(%i1) f (x) := h (x) / g (x);
h(x)
(%o1) f(x) := ----
g(x)
(%i2) g (x) ::= block (print ("x + 99 is equal to", x),
return (x + 99));
(%o2) g(x) ::= block(print("x + 99 is equal to", x),
return(x + 99))
(%i3) h (x) ::= block (print ("x - 99 is equal to", x),
return (x - 99));
(%o3) h(x) ::= block(print("x - 99 is equal to", x),
return(x - 99))
(%i4) macroexpansion: false;
(%o4) false
(%i5) f (a * b);
x - 99 is equal to x
x + 99 is equal to x
a b - 99
(%o5) --------
a b + 99
(%i6) dispfun (f);
h(x)
(%t6) f(x) := ----
g(x)
(%o6) done
(%i7) f (a * b);
x - 99 is equal to x
x + 99 is equal to x
a b - 99
(%o7) --------
a b + 99
macroexpansionがexpandの時、
マクロ関数は一度コールされ、
コールする式は変更されません。
(%i1) f (x) := h (x) / g (x);
h(x)
(%o1) f(x) := ----
g(x)
(%i2) g (x) ::= block (print ("x + 99 is equal to", x),
return (x + 99));
(%o2) g(x) ::= block(print("x + 99 is equal to", x),
return(x + 99))
(%i3) h (x) ::= block (print ("x - 99 is equal to", x),
return (x - 99));
(%o3) h(x) ::= block(print("x - 99 is equal to", x),
return(x - 99))
(%i4) macroexpansion: expand;
(%o4) expand
(%i5) f (a * b);
x - 99 is equal to x
x + 99 is equal to x
a b - 99
(%o5) --------
a b + 99
(%i6) dispfun (f);
h(x)
(%t6) f(x) := ----
g(x)
(%o6) done
(%i7) f (a * b);
a b - 99
(%o7) --------
a b + 99
macroexpansionがexpandの時、
マクロ関数は一度コールされ、
コールする式が変更されます。
(%i1) f (x) := h (x) / g (x);
h(x)
(%o1) f(x) := ----
g(x)
(%i2) g (x) ::= block (print ("x + 99 is equal to", x),
return (x + 99));
(%o2) g(x) ::= block(print("x + 99 is equal to", x),
return(x + 99))
(%i3) h (x) ::= block (print ("x - 99 is equal to", x),
return (x - 99));
(%o3) h(x) ::= block(print("x - 99 is equal to", x),
return(x - 99))
(%i4) macroexpansion: displace;
(%o4) displace
(%i5) f (a * b);
x - 99 is equal to x
x + 99 is equal to x
a b - 99
(%o5) --------
a b + 99
(%i6) dispfun (f);
x - 99
(%t6) f(x) := ------
x + 99
(%o6) done
(%i7) f (a * b);
a b - 99
(%o7) --------
a b + 99
デフォルト値: true
mode_checkpがtrueの時、
mode_declareはバインドされた変数のモードをチェックします。
デフォルト値: false
mode_check_errorpがtrueの時、
mode_declareはエラーをコールします。
デフォルト値: true
mode_check_warnpがtrueの時、
モードエラーが記述されます。
mode_declareは、
その後の関数の翻訳やコンパイルのために
変数と関数のモードを宣言するのに使われます。
mode_declareは、通常、
関数定義の始めやMaximaスクリプトの始めに置かれたり、対話プロンプトで実行されたりします。
mode_declareの引数は、
変数とモードから成る対です。
モードは
boolean, fixnum, number, rational, floatのいずれか1つです。
変数それぞれは、
同じモードを持つように宣言される変数すべてのリストも取り得ます。
もし変数が配列で、かつ、参照される配列のすべての要素が値を持つなら、 なら、
array(yi, dim1, dim2, ...)
よりむしろarray (yi, complete, dim1, dim2, …)を
最初に配列のバインドを宣言する時に使うべきです。
もし配列の要素すべてが
モードfixnum (float)なら、
completeの代わりにfixnum (float)を使ってください。
もし配列のすべての要素が同じモード―mとしましょう―なら、
効率的な翻訳のためには、
mode_declare (completearray (yi), m))
を使うべきです。
配列を使う数値コードは、例えば、10 x 10の浮動小数点配列のために
mode_declare (completearray (a [10, 10]), float)
というように、期待される配列サイズを宣言することでより速く実行されるかもしれません
引数としてfunction (f_1, f_2, ...)を使うことで
関数の結果のモードを宣言することができます;
ここでf_1, f_2, …は関数名です。
例えば、式
mode_declare ([function (f_1, f_2, ...)], fixnum)
は、
f_1, f_2, ...が返す値が1ワード整数であることを宣言します。
modedeclareはmode_declareと同義です。
mode_declareとmacrosで
例えば、flonumsのリストのリストや他の合成データオブジェクトを宣言するのに
使われる特殊形式。
mode_identityの最初の引数は、mode_declareに与えられるような
プリミティブな値モード名(すなわち、float, fixnum, number,
list, anyのいずれか)であり、
二番目の引数は、評価され、mode_identityの値として返される式です。
しかしながら、もし戻り値が最初の引数で宣言されたモードによって許されていないなら、
エラーか警告がシグナルされます。
重要なことは、MaximaによってLisp翻訳器に命じた式のモードが、二番目の引数のなかで続く一切から独立して、最初の引数として与えられるそれだということです。
例えば、x: 3.3; mode_identity (fixnum, x);はエラーをもたらします。
mode_identity (flonum, x)は3.3を返します。
これは多くの使い道があります。例えば、もしfirst (l)が数を返すと知っていたなら、
mode_identity (number, first (l))と書くかもしれません。
しかしながら、それをするもっと効率的な方法は、
firstnumb (x) ::= buildq ([x], mode_identity (number, first(x)));
のように新しいプリミティブを定義し、
そして数のリストの最初の要素を取る時毎回firstnumbを使うことです。
シンボルf_1, ..., f_nの関数定義をアンバインドします。
引数は、(:=もしくはdefineで生成された)通常の関数名もしくは(::=で生成された)マクロ関数をとります。
remfunction (all)は関数定義すべてをアンバインドします。
remfunctionは引数をクォートします。
remfunctionは、関数定義はアンバインドされたシンボルのリストを返します。
シンボルに関数定義がなければ、シンボルの代わりにfalseを返します。
remfunctionは配列関数すなわち添字付き関数には適用されません。
これらのタイプの関数にはremarrayを適用します。
デフォルト値: true
savedefがtrueの時、
関数が解釈される時に
ユーザー関数のMaximaバージョンが保持されます。
これは、定義がdispfunによって表示されることを許し、
関数が編集されることを許します。
savedefがfalseの時、
解釈された関数の名前は、functionsリストから取り除かれます。
デフォルト値: true
transcompileがtrueの時、
translateとtranslate_fileは
翻訳コードをコンパイルにより適したものにする宣言を生成します。
compfileは実行中transcompile: trueを設定します。
ユーザー定義関数f_1, …, f_nをMaxima言語からLispに翻訳し、 Lisp翻訳を評価します。 通常、翻訳された関数は元の関数より速く実行されます。
translate (all)やtranslate (functions)は、
ユーザー定義関数すべてを翻訳します。
翻訳される関数は、
より効率的なコードを生成するために可能な時は
先頭にmode_declareコールを含むべきです。
例えば:
f (x_1, x_2, ...) := block ([v_1, v_2, ...],
mode_declare (v_1, mode_1, v_2, mode_2, ...), ...)
ここで、x_1, x_2, ... は関数のパラメータであり、 v_1, v_2, ...はローカル変数です。
もしsavedefがfalseなら(以下を参照してください)
翻訳された関数の名前は、functionsリストから削除され、
propsリストに加えられます。
完全にデバッグされない限り、関数は翻訳すべきではありません。
式は整理されていると仮定されます;
もしされていないなら、厳密ですが、最適でないコードが生成されます。
従って、
ユーザーは
simpスイッチをfalse―翻訳される式の整理を抑制します―
に設定すべきではありません。
スイッチtranslateは、もしtrueなら、
ユーザー関数のLispへの自動翻訳をもたらします。
LispとMaximaのバージョンの間である非互換性が存在する可能性があるので、
翻訳された関数は
翻訳前にした方法を同一に動作するわけではないことに注意してください。
原則として、
もし変数のいずれかがmode_declareされた標準有理式(CRE)なら
複数の引数を取るrat関数とratvars関数は使うべきではありません。
また、
prederror: false設定は翻訳されません。
savedef - もしtrueなら、
関数がtranslateされた時、Maximaバージョンのユーザー関数を残すようにします。
これは、定義をdispfunで表示することを可能にし、
関数を編集することを可能にします。
transrun - もしfalseなら、
すべての関数について、翻訳バージョンではなく、
インタープリトされるバージョン(まだあると仮定して)が実行されるようにします。
translateが返す結果は、翻訳された関数名のリストです。
MaximaコードのファイルをLispコードのファイルに翻訳します。
translate_fileは3つのファイル名のリストを返します:
Maximaファイル名、Lispファイル名、翻訳についての追加情報を含むファイル名。
translate_fileは引数を評価します。
translate_file ("foo.mac"); load("foo.LISP")は、
例えば、''と%の利用といった若干の制約を除いて、
コマンドbatch ("foo.mac")と同じです。
translate_file (maxima_filename)は
Maximaファイルmaxima_filenameを
同様に名付けらたLispファイルに翻訳します。
例えば、foo.macはfoo.LISPに翻訳されます。
Maximaのファイル名はディレクトリ名を含むかもしれません。
その場合、Lisp出力ファイルは、Maxima入力が来たのと同じディレクトリに書かれます。
translate_file (maxima_filename, lisp_filename)は、
Maximaファイルmaxima_filenameをLispファイルlisp_filenameに翻訳します。
translate_fileは、どんなものでも、lisp_filenameの
ファイル名の拡張子を無視します;
Lisp出力ファイルのファイル名の拡張子は、いつもLISPです。
Lispファイル名はディレクトリ名を含むかもしれません。
その場合、Lisp出力ファイルは指定されたディレクトリに書かれます。
translate_fileは、翻訳器のファイル
様々な度合いの厳しさの翻訳器警告メッセージのファイルも書き出します。
このファイルのファイル名拡張子は UNLISPです。
このファイルは、翻訳されたコードの中のバグを追跡するために、
あいまいかもしれませんが、価値ある情報を含むかもしれません。
UNLISPファイルはいつもMaxima入力が来るのと同じディレクトリに書かれます。
translate_fileは
Lispコードがコンパイルされるすぐに宣言や定義が効力を発揮するようにするLispコードを発行します。
このトピックに関してさらに知るにはcompile_fileを参照してください。
tr_array_as_ref,
tr_bound_function_applyp,
tr_exponent,
tr_file_tty_messagesp,
tr_float_can_branch_complex,
tr_function_call_default,
tr_numer,
tr_optimize_max_loop,
tr_semicompile,
tr_state_vars,
tr_warnings_get,
tr_warn_bad_function_calls,
tr_warn_fexpr,
tr_warn_meval,
tr_warn_mode,
tr_warn_undeclared,
tr_warn_undefined_variable
も参照してください。
デフォルト値: true
transrunがfalseの時、
すべての関数について、翻訳バージョンではなく、
インタープリトされるバージョン(まだあると仮定して)が実行されるようにします。
デフォルト値: true
もしtranslate_fast_arraysがfalseなら、
translate_fileが発行するLispコードの中の配列参照は、
tr_array_as_refによって影響されます。
tr_array_as_refがtrueの時、
配列名は評価されます。
そうでなければ、配列名は翻訳されたコードの中で文字リテラルとして現れます。
もしtranslate_fast_arraysがtrueなら、
tr_array_as_refは効果を持ちません。
デフォルト値: true
tr_bound_function_applypがtrueの時、
もし(関数引数のような)バインドされた変数が関数として使われていることが見つかったら
Maximaは警告を与えます。
tr_bound_function_applypは、
そんな場合に生成されたコードに影響しません。
例えば、
g (f, x) := f (x+1)のような式は警告メッセージをトリガーします。
デフォルト値: false
tr_file_tty_messagespがtrueの時、
ファイルの翻訳中に
translate_fileが生成するメッセージがコンソールに表示され、
falseの時、ファイルの翻訳に関するメッセージは
UNLISPファイルに挿入されるだけです。
デフォルト値: true
Maxima-to-Lisp翻訳器に
translator to assume that
関数acos, asin, asec, acscが複素数の結果を返すことができることを仮定するように命じます。
tr_float_can_branch_complexの表面上の効果は以下の通りです。
しかしながら、このフラグは翻訳器出力上の効果を持ちません。
trueの時、
たとえ (mode_declareが設定したように)xがモードfloatでも
acos(x)はモードanyです。
falseの時、
xがモードfloatの時だけ
acos(x)はモードfloatです。
デフォルト値: general
falseは、あきらめてmevalをコールすることを意味し、
exprは、引数が固定されたLisp関数を仮定することを意味します。
general、デフォルトは
mexprsやmlexprsにはよいがmacrosにはよくないコードを与えます。
generalは、コンパイルされたコードの中で変数バインドが正確であることを保証します。
generalモードでは、
F(X)を翻訳する時、もしFがバインドされた変数なら、
apply (f, [x])を意味すると仮定され、適切な警告と合わせてそのように翻訳されます。
これをオフにする必要はありません。
デフォルト設定で警告メッセージがないことは、
Maximaインタープリタと、翻訳、コンパイルされたコードの完全互換性を意味します。
デフォルト値: false
tr_numerがtrueの時、
numerプロパティは
それらを持つアトム、例えば、%piに使われます。
デフォルト値: 100
tr_optimize_max_loopは、
翻訳器のマクロ展開と最適化パスが形式を検討する際繰り返す最大回数です。
これはマクロ展開エラーや終了しない最適化プロパティをキャッチします。
デフォルト値: false
tr_semicompileがtrueの時、
translate_fileとcompfileは、
マクロ展開されたが、Lispコンパイラによって機械語にコンパイルされない形式を出力します。
デフォルト値:
[transcompile, tr_semicompile, tr_warn_undeclared, tr_warn_meval, tr_warn_fexpr, tr_warn_mode, tr_warn_undefined_variable, tr_function_call_default, tr_array_as_ref,tr_numer]
翻訳された出力の形式に影響するスイッチのリスト。 翻訳器をデバッグしようとする時 この情報はシステムの人たちに役に立ちます。 翻訳された生成物を与えられた状態で生成されるべきだったものと比較することによって、 バグを追跡することが可能です。
現在の翻訳の間に翻訳器が与える警告のリストを印字します。
デフォルト値: true
- 翻訳時にされた不適切な宣言のせいで正確でないかもしれない関数コールが行われている時、 警告を与えます。
デフォルト値: compfile
- もしFEXPRに遭遇したら、警告を与えます。 FEXPRは、通常、翻訳コードの中で出力されるべきではありません。 合法で特殊なプログラム形式はすべて翻訳されます。
デフォルト値: compfile
- もし関数mevalがコールされたら、警告を与えます。
もしmevalがコールされたら、それは翻訳の中の問題を示します。
デフォルト値: all
- 変数がそのモードに不適切な値を割り当てられた時、警告を与えます。
デフォルト値: compile
- 未宣言変数についての警告をいつTTYに送るかを決めます。
デフォルト値: all
- 未定義のグローバル変数が見られた時、警告を与えます。
MaximaファイルfilenameをLispに翻訳し、Lispコンパイラを実行し、 もし翻訳とコンパイルが成功したら、コンパイルされたコードをMaximaにロードします。
compile_fileは4つのファイル名のリストを返します:
元のMaximaファイル、Lisp翻訳、翻訳時ノート、コンパイルされたコード。
もしコンパイルが失敗したら、4番目の項目はfalseです。
Lispコードがコンパイルされると(コンパイルされたコードをロードすることなしに)すぐに
いくつかの宣言と定義は効力を発揮します。
これらは:=演算子で定義された関数、
::=演算子で定義されたマクロ、
alias, declare,
define_variable, mode_declare,
infix, matchfix,
nofix, postfix, prefix,
compfile
を含みます。
コンパイルされたコードがロードされるまで
割り当てと関数コールは評価されません。
特に、Maximaファイルの中で、
(tr_numer, など)翻訳フラグへの割り当ては翻訳時に効果を持ちません。
filenameは:lisp文を含むことができません。
compile_fileは引数を評価します。
MaximaコードのファイルをLispに翻訳する時、
ファイルの中で見る関数が翻訳された関数としてコールされるか、コンパイルされた関数としてコールされるか、また、どの関数がMaxima関数か未定義なのか、翻訳器が知ることは重要です。
この宣言をファイルの先頭に置くことは、
たとえまだLisp関数値を持たないシンボルがコール時にそれを持つだろうが、
それを知らせます。
fnがLisp関数になるつもりであることを翻訳器が知らない時、
(MFUNCTION-CALL fn arg1 arg2 ...)が生成されます。
Previous: Macros, Up: Function Definition [Contents][Index]