Next: Macros, Previous: Introduction to Function Definition, Up: Function Definition [Contents][Index]
Maximaの中で関数を定義するためには、
:=
演算子を使います。
例えば、
f(x) := sin(x)
は関数 f
を定義します。
匿名関数も lambda
を使って生成することができます。
例えば、
f(i,j) := block ([], ...); map (lambda ([i], i+1), l)
は、項それぞれに1を足したリストを返しますが、
lambda ([i, j], ...)
をf
の代わりに使うことができます。
(訳注: 元マニュアルの編集ミスでしょうか。以下の内容が一貫すると思います。
f(i) := i+1; map (f, l)
は、項それぞれに1を足したリストを返しますが、
lambda ([i], i+1)
をf
の代わりに使うことができます。)
余分な引数のリストに割り当てられる最後の引数を持つことで、 引数が可変の関数も定義できます:
(訳注:
最後の引数変数を[]
でくくると、残りの引数のリストがその引数変数に割り当てられます。)
(%i1) f ([u]) := u; (%o1) f([u]) := u (%i2) f (1, 2, 3, 4); (%o2) [1, 2, 3, 4] (%i3) f (a, b, [u]) := [a, b, u]; (%o3) f(a, b, [u]) := [a, b, u] (%i4) f (1, 2, 3, 4, 5, 6); (%o4) [1, 2, [3, 4, 5, 6]]
関数の右辺は式です。 従って、もし一連の式が欲しいなら、
f(x) := (expr1, expr2, ...., exprn);
とします。 exprnの値が関数が返すものになります。
もし関数内部のある式からreturn
したいなら、
block
とreturn
を使わなければいけません。
block ([], expr1, ..., if (a > 10) then return(a), ..., exprn)
はそれ自身式で、関数定義の右辺にとって代わることができます。 この際、最後の式よりも早くreturnが起こるかもしれません。
ブロックの中の最初の[]
は、
[a: 3, b, c: []]
のように、変数と変数割り当てのリストを含むかもしれません。
[a: 3, b, c: []]
は、3つの変数a
,b
,c
が
コードが、block
内部やblock
内部からコールされた関数内部で実行される限り、
グローバル値を参照しないように、しかしむしろ特別な値を持つようにします。
変数がブロックの開始から抜ける時間まで続くので、これは、動的バインドと呼ばれます。
一旦block
から戻るか、そこから出ると、(もし存在するなら)変数の古い値が戻されます。
この方法で変数を保護することは確かによい考えです。
ブロック変数に関する割り当ては、並列に行われることに注意してください。
これは、もし先にc: a
を使ったら、c
の値はブロックにちょうど入った時、まだ
a
がバインドされる前のa
の値であることを意味します。
例えば、
block ([a: a], expr1, ... a: a+3, ..., exprn)
のような何かを実行することは、
a
の外部の値を変更されないよう保護しますが、その値がなんだったかアクセス可能にします。
割り当ての右辺は、バインドが起こる前に入る文脈の中で評価されます。
Using just
ただblock ([x], ...
を使うことは、
ちょうどまるで新しいMaximaセッションに入ったかのように、x
がそれ自身を値として持つようにします。
関数の実際の引数は、ブロックの変数と厳密に同じ方法で扱われます。 例えば、
f(x) := (expr1, ..., exprn);
と
f(1);
では、式の評価に関して、まるで
block ([x: 1], expr1, ..., exprn)
を実行したかのような類似の文脈を持ちます。
定義の右辺がランタイムで計算される時、
関数内部では、define
とたぶんbuildq
を使うことが役に立ちます。
Inside functions, when the right hand side of a definition, may be computed at runtime, it is useful to use define
and possibly buildq
.
配列関数は、初めて与えられた引数でコールされた時、関数値を記憶し、 同じ引数が与えられた時、再計算することなしに記憶した値を返します。 そんな関数はしばしばメモ化関数と呼ばれます。
配列関数名は、(グローバルリストfunctions
ではなく)
グローバルリストarrays
に追加されます。
arrayinfo
は
記憶された値を持つ引数のリストを返し、
listarray
は記憶された値を返します。
dispfun
とfundef
は配列関数の定義を返します。
arraymake
は、通常の関数に対するfunmake
のように、
配列関数コールを構成します。
arrayapply
は、
通常の関数に対するapply
のように、
配列関数をその引数に適用します。
配列関数に対して、map
に厳密に似たものはありません。
map(lambda([x], a[x]), L)
または
makelist(a[x], x, L)
―Lはリストです―は、目的からそれほど遠くありませんけれども。
remarray
は、
通常の関数に対するremfunction
のように、
(記憶された関数値も含めて、)配列関数の定義を削除します。
kill(a[x])
は、配列関数aの引数xに関して記憶された
値を削除します;
次回、引数xでaがコールされた時、
関数値は再計算されます。
しかしながら、
関数定義も削除するkill(a)
またはremarray(a)
を除いて、
記憶された値すべてを一度に削除する方法はありません。
Next: Macros, Previous: Introduction to Function Definition, Up: Function Definition [Contents][Index]