Next: Debugging, Previous: Function Definition [Contents][Index]
Next: Garbage Collection, Previous: Program Flow, Up: Program Flow [Contents][Index]
MaximaはLispで書かれており、
Lisp関数や変数をMaximaからアクセスしたり、その逆が簡単にできます。
LispとMaximaのシンボルは命名の慣例で区別されます。
ドル記号$
で始まるLispシンボルは、ドル記号なしのMaximaシンボルに対応します。
クエスチョンマーク?
で始まるMaximaシンボルは、クエスチョンマークなしのLispシンボルに対応します。
例えば、Maximaシンボルfoo
はLispシンボル$FOO
に対応し、
Maximaシンボル?foo
はLispシンボルFOO
に対応します。
?foo
は、?
とfoo
の間にスペースを入れずに書くことに注意してください。でないと、それはdescribe ("foo")
に間違えられます。
Lispシンボルの中に、ハイフン-
やアスタリスク*
、他の特殊文字があれば、
Maximaのコードの中では、バックスラッシュ\
でエスケープしないといけません。
例えば、Lispの識別子 *foo-bar*
は、Maximaでは、?\*foo\-bar\*
と書きます。
Maximaセッションの中で、Lispコードを実行できます。
特殊コマンド:lisp
を使って、
(1つか複数のフォームを含む)Lispの一行を実行できます。例えば、
(%i1) :lisp (foo $x $y)
は、Lisp関数foo
をMaxima変数x
, y
を引数としてコールします。
:lisp
構成子は
対話プロンプトやbatch
やdemo
によって処理されるファイルの中で使えますが、
load
, batchload
, translate_file
, compile_file
が
処理するファイルの中では使えません。
関数to_lisp()
を実行すると、対話的なLispセッションが始まります。
(to-maxima)
を入力すると、Lispセッションを終了してMaximaに戻ります。
Lispの関数や変数を、Maximaで通常の関数名、変数名(特殊な句読点のない名前)に見せるには、
Lispの名前をドル記号$
で始めなければなりません。
Maximaでは、識別子の中の大文字、小文字が区別されます。 LispとMaximaの間の名前変換を決めるルールがあります。
$foo
や$FOO
、$Foo
はすべて
Maximaのfoo
に対応します。
でも、これはデフォルトで、
Lispリーダが$foo
, $FOO
, $Foo
を
Lispシンボル$FOO
に変換するからです。
|$FOO|
, |$foo|
はそれぞれ、Maximaのfoo
, FOO
に対応します。
|$Foo|
はMaximaのFoo
に対応します。
#$
Lispマクロを使うと、Maximaの式をLispコードの中で使うことができます。
#$expr$
はMaximaの式exprと同値なLispの式に展開されます。
(msetq $foo #$[x, y]$)
これは以下のように入力するのと同じ効果です。
(%i1) foo: [x, y];
Lisp関数displa
は、Maximaフォーマットで式を表示します。
(%i1) :lisp #$[x, y, z]$ ((MLIST SIMP) $X $Y $Z) (%i1) :lisp (displa '((MLIST SIMP) $X $Y $Z)) [x, y, z] NIL
Maximaで定義された関数は、通常のLisp関数ではありません。
Lisp関数mfuncall
は、Maxima関数をコールします。
例えば:
(%i1) foo(x,y) := x*y$ (%i2) :lisp (mfuncall '$foo 'a 'b) ((MTIMES SIMP) A B)
以下のLisp関数は、Maximaパッケージの中でシャドウされています。
complement continue // float functionp array exp listen signum atan asin acos asinh acosh atanh tanh cosh sinh tan break gcd
Next: Introduction to Program Flow, Previous: Lisp and Maxima, Up: Program Flow [Contents][Index]
数式処理は膨大なゴミ(最終的には使われない一時的な、もしくは中間の結果)を生む傾向があり、 ゴミの効率的な取り扱いは、プログラムをうまく完了させるために非常に重要な場合があります。
(SunOS 4.0やBSDの幾つかを含む)mprotectシステムコールが利用可能なUNIXシステム 上でのGCLでは、階層化(stratified)ガーベッジコレクションが利用可能です。 これは、ガーベッジコレクションを最近書き込まれたページに限定します。 GCLドキュメントのALLOCATEやGBCを参照してください。 Lispレベルで(setq si::*notify-gbc* t)を実行すると、どの領域がより多くの空間を必要としているか決めるのに役立つでしょう。
Maximaを走らせる他のLispについては、 そのLispのGCの制御の仕方に関するドキュメントを調べてください。
Next: Functions and Variables for Program Flow, Previous: Garbage Collection, Up: Program Flow [Contents][Index]
Maximaは、
go
のようなもっとプリミティブな構成子はもちろん、
繰り返しのためにdo
ループを提供します。
Previous: Introduction to Program Flow, Up: Program Flow [Contents][Index]
コールスタック、すなわち、 現在アクティブな関数をコールした関数のリスト、を印字します。
backtrace()
はコールスタック全体を印字します。
backtrace (n)
は、
現在アクティブな関数を含めて、n個の直近の関数を印字します。
backtrace
は、
(デバッグの文脈でだけでなく、)
スクリプト、関数、対話プロンプトからコールすることができます。
例:
backtrace()
はコールスタック全体を印字します。
(%i1) h(x) := g(x/7)$ (%i2) g(x) := f(x-11)$ (%i3) f(x) := e(x^2)$ (%i4) e(x) := (backtrace(), 2*x + 13)$ (%i5) h(10); #0: e(x=4489/49) #1: f(x=-67/7) #2: g(x=10/7) #3: h(x=10) 9615 (%o5) ---- 49
backtrace (n)
は、
現在アクティブな関数を含めて、n個の直近の関数を印字します。
(%i1) h(x) := (backtrace(1), g(x/7))$ (%i2) g(x) := (backtrace(1), f(x-11))$ (%i3) f(x) := (backtrace(1), e(x^2))$ (%i4) e(x) := (backtrace(1), 2*x + 13)$ (%i5) h(10); #0: h(x=10) #0: g(x=10/7) #0: f(x=-67/7) #0: e(x=4489/49) 9615 (%o5) ---- 49
do
文は繰り返しを実行するために使われます。
その強力な一般性のために、
do
文は2編で記述されます。
最初、通常の形式が
(Fortran, Algol, PL/I, など)いくつかの他のプログラミング言語の中で使われるそれ
との類似で与えられます;
それから、他の特長が言及されます。
この形式の、終了条件に関してだけ違う3つの別形があります。 それらは:
for variable: initial_value step increment
thru limit do body
for variable: initial_value step increment
while condition do body
for variable: initial_value step increment
unless condition do body
(代わりに、step
は終了条件や範囲の後与えられるかもしれません。)
initial_value, increment, limit, bodyは、
任意の式を取り得ます。
もし増分が1なら、 "step 1
"は省略できます。
do
文の実行は、最初
initial_valueを variable (今後、制御変数と呼びます)
に割り当てることによって処理されます。
そして:
(1) もし制御変数が thru
指定の範囲を越えたら、もしくは、
unless
の条件が true
なら、
もしくは、 while
の条件が false
なら、
do
は終了します。
(2) bodyが評価されます。
(3) 増分が制御変数に足されます。
終了条件が満たされるまで、
いずれかが満たされる時 do
が終了する複数の終了条件を与えることもできます。
一般的に、 thru
テストは、
もし incrementが非負なら、制御変数が limitよりも大きい時、
または、もし incrementが負なら、制御変数が limitよりも小さい時、
満たされます。
incrementと limitは、この不等式が決定できる限り、数値でない式も取り得ます。
しかしながら、
do
文が入力された時
incrementが構文法的に負(例えば負の数)でない限り、
Maximaは、 do
が実行される時、正と仮定します。
もし正でないなら、
do
は適切に終了しないかもしれません。
limit, increment, 終了条件は、ループを通して毎回評価されることに注意してください。
もしこれらのいずれかがおおくの計算を含み、
bodyの実行中すべてで変わらない結果をもたらすなら、
do
に先立って変数をそれらの値に設定し、その変数を
do
形式の中で使うことはもっと効率的です。
do
文が通常返す値は、アトム done
です。
しかしながら、
早い時点で do
から抜けて任意の望みの値を与えるために、
関数 return
を bodyの中で使うことができます。
しかしながら、 block
の中で起こる do
の中の return
は、
do
だけから抜けて、 block
からは抜けないことに注意してください。
do
から囲んでいる block
に抜けるために、
go
関数は使えないことにも注意してください。
制御変数はいつも do
にローカルです。
従って、
do
の外側の同じ名前を持つ変数の値に影響することなく、任意の変数が使えます。
制御変数は、 do
が終了した後、バインドされていません。
(%i1) for a:-3 thru 26 step 7 do display(a)$ a = - 3 a = 4 a = 11 a = 18 a = 25
(%i1) s: 0$ (%i2) for i: 1 while i <= 10 do s: s+i; (%o2) done (%i3) s; (%o3) 55
条件while i <= 10
は、
unless i > 10
と、また、thru 10
と同値であることに注意してください。
(%i1) series: 1$ (%i2) term: exp (sin (x))$ (%i3) for p: 1 unless p > 7 do (term: diff (term, x)/p, series: series + subst (x=0, term)*x^p)$ (%i4) series; 7 6 5 4 2 x x x x x (%o4) -- - --- - -- - -- + -- + x + 1 90 240 15 8 2
以上は、e^sin(x)
のTaylor級数の8項を与えます。
(%i1) poly: 0$ (%i2) for i: 1 thru 5 do for j: i step -1 thru 1 do poly: poly + i*x^j$ (%i3) poly; 5 4 3 2 (%o3) 5 x + 9 x + 12 x + 14 x + 15 x (%i4) guess: -3.0$ (%i5) for i: 1 thru 10 do (guess: subst (guess, x, 0.5*(x + 10/x)), if abs (guess^2 - 10) < 0.00005 then return (guess)); (%o5) - 3.162280701754386
この例は、
Newton-Raphson反復を最大10回使って、
10の負の平方根を計算します。
もし収束基準が満たされないなら、
戻り値はdone
になります。
いつもある量を制御変数に加える代わりに、
繰り返しそれぞれで量をある他の方法で換えたい時があるかもしれません。
この場合、
step increment
の代わりに
next expression
を使うことができます。
これは、ループの間、
制御変数が毎回expressionの評価結果に設定されるようにします。
(%i6) for count: 2 next 3*count thru 20 do display (count)$ count = 2 count = 6 count = 18
for variable: value ...do...
の代わりとして、
構文法for variable from value ...do...
が使えます。
これは、
from value
を
step
やnext
値の後や終了条件の後に置くことを許します。
もしfrom value
が省略されたら、
初期値として1が使われます。
制御変数が実際には決して使われないような繰り返しを実行することに興味があることがあるかもしれません。 それゆえに、 貧弱な初期推測を使って5の平方根を計算する以下の例にあるように、 初期化と更新情報を省略して終了条件だけ与えることが許されます。
(%i1) x: 1000$ (%i2) thru 20 do x: 0.5*(x + 5.0/x)$ (%i3) x; (%o3) 2.23606797749979 (%i4) sqrt(5), numer; (%o4) 2.23606797749979
もし望むなら、終了条件さえ完全に省略し、
無限にbodyを評価し続けるdo body
だけを与えることもできます。
この場合、関数return
がdo
の実行を終了するのに使われるべきです。
(%i1) newton (f, x):= ([y, df, dfx], df: diff (f ('x), 'x), do (y: ev(df), x: x - f(x)/y, if abs (f (x)) < 5e-6 then return (x)))$ (%i2) sqr (x) := x^2 - 5.0$ (%i3) newton (sqr, 1000); (%o3) 2.236068027062195
(return
が実行された時、
x
の現在値を
do
の値として返そうとすることに注意してください。
do
がブロックの最後の文なので、
block
から抜けて、
do
の値が
block
の値として返されます。)
do
のもう1つ別の形式がMaximaで利用可能です。構文法は:
for variable in list end_tests do body
listの要素は、
bodyの繰り返しのそれぞれで
variable
に連続的に割り当てられる任意の式です。
オプションの終了テストend_testsは、
do
の実行を終了するのに使うことができます;
そうでなければ、
listが使い果たされた時、または、
bodyの中で
return
が実行された時、
終了します。
(実際には、list
は非アトムの任意の式を取り得えて、連続的な部分が取られます。)
(%i1) for f in [log, rho, atan] do ldisp(f(1))$ (%t1) 0 (%t2) rho(1) %pi (%t3) --- 4 (%i4) ev(%t3,numer); (%o4) 0.78539816
expr_1, …, expr_nを1つずつ評価し、
もしエラーが起こらないなら、[expr_n]
(リスト)を返します。
もしいずれかの引数の評価中にエラーが起こったら、
errcatch
はエラーが伝搬することを抑制し、
引数をこれ以上評価せずに空のリスト[]
を返します。
errcatch
は
もしエラーがチャッチされないならbatch
を終了させるエラーが起こるかもしれないと疑うような
batch
ファイルで役立ちます。
expr_1, ..., expr_nを評価して印字します。
そして、エラーがあれば、トップレベルMaximaか直近のerrcatch
に戻るようにします。
変数error
はエラーを記述するリストに設定されます。
error
の最初の要素はフォーマット文字列です。
引数expr_1, ..., expr_nの中の文字列すべてを結合したものです。
残りの要素は文字列でない引数の値です。
errormsg()
はerror
をフォーマットし印字します。
これは直近のエラーメッセージを効果的に再印字します。
デフォルト値: 10
error_size
は、
現れる式のサイズに従って、エラーメッセージを変更します。
もし式のサイズが、Lisp関数ERROR-SIZE
によって決定されるように)
error_size
より大きいなら、
式は、メッセージの中で、シンボルで置き換えられ、
シンボルは式に割り当てられます。
シンボルはリストerror_syms
から取られます。
そうでなければ、式はerror_size
より小さく、
メッセージの中に式が表示されます。
error
とerror_syms
も参照してください。
例:
U
のサイズは、ERROR-SIZE
で決められるように、24です。
(%i1) U: (C^D^E + B + A)/(cos(X-1) + 1)$ (%i2) error_size: 20$ (%i3) error ("Example expression is", U); Example expression is errexp1 -- an error. Quitting. To debug this try debugmode(true); (%i4) errexp1; E D C + B + A (%o4) -------------- cos(X - 1) + 1 (%i5) error_size: 30$ (%i6) error ("Example expression is", U); E D C + B + A Example expression is -------------- cos(X - 1) + 1 -- an error. Quitting. To debug this try debugmode(true);
デフォルト値: [errexp1, errexp2, errexp3]
エラーメッセージの中で、
error_size
より大きな式はシンボルで置き換えられ、
シンボルは式に設定されます。
シンボルはリストerror_syms
から取られます。
最初の大きすぎる式は、error_syms[1]
で置き換えられ、
2番目は、error_syms[2]
で置き換えられ、などなど。
もし大きすぎる式がerror_syms
の要素よりもあれば、
シンボルは自動的に構成されます。
n番目のシンボルはconcat ('errexp, n)
と同値です。
error
とerror_size
も参照してください。
直近のエラーメッセージを再印字します。
変数error
はメッセージを保持し、
errormsg
はそれをフォーマットし印字します。
デフォルト値: true
false
の時、エラーメッセージの出力は抑制されます。
オプション変数errormsg
は
ブロックの中でローカル値に設定することはできません。
errormsg
のグローバル値が常に存在します。
(%i1) errormsg; (%o1) true (%i2) sin(a,b); Wrong number of arguments to sin -- an error. To debug this try: debugmode(true); (%i3) errormsg:false; (%o3) false (%i4) sin(a,b); -- an error. To debug this try: debugmode(true);
オプション変数errormsg
はブロックの中でローカル値に設定できません。
(%i1) f(bool):=block([errormsg:bool], print ("value of errormsg is",errormsg))$ (%i2) errormsg:true; (%o2) true (%i3) f(false); value of errormsg is true (%o3) true (%i4) errormsg:false; (%o4) false (%i5) f(true); value of errormsg is false (%o5) false
繰り返しで使われます。
Maximaの繰り返し機能の記述に関しては、do
を参照してください。
制御を
go
の引数でタグ付けされたブロックの文に移すために
block
内部で使われます。
文をタグ付けするには、
その文の前に、
アトムの引数を
block
の中の別の文として
先行させてください。
例えば:
block ([x], x:1, loop, x+1, ..., go(loop), ...)
go
の引数は、同じblock
の中に現れるタグの名前でなければいけません。
go
を含むblock
以外のblock
の中のタグに移るために、
go
を使うことはできません。
条件評価を表します。
if
式の様々な形が認識されます。
if cond_1 then expr_1 else expr_0
は、
もしcond_1がtrue
評価されたらexpr_1に*評*価*され、
そうでなければ式はexpr_0に評価されます。
コマンド if cond_1 then expr_1 elseif cond_2 then expr_2 elseif ... else expr_0
は、
もしcond_kがtrue
、かつ、先行する条件がすべてfalse
なら、
expr_kに評価されます。
もし条件のいずれもtrue
でないなら、式はexpr_0
に評価されます。
もしelse
がないなら、
最後にelse false
が仮定されます。
すなわち、コマンド if cond_1 then expr_1
は、
if cond_1 then expr_1 else false
と同値で、
コマンド if cond_1 then expr_1 elseif ... elseif cond_n then expr_n
は、
if cond_1 then expr_1 elseif ... elseif cond_n then expr_n else false
と同値です。
選択肢expr_0, …, expr_nは、任意のMaxima式を取り得ます。
入れ子のif
式もあり得ます。
選択肢は、
対応する条件がtrue
でない限り、
整理も評価もされません。
条件cond_1, ..., cond_nは、潜在的に、また、実際に
true
かfalse
に評価される式です。
条件が実際にはtrue
にもfalse
にも評価されない時、
if
の振る舞いはグローバルフラグprederror
で決定されます。
prederror
がtrue
の時、
もし評価された条件のいずれかがtrue
にもfalse
にもならなかったら
、エラーになります。
そうでなければ、true
にもfalse
にも評価されない条件が受け入れられ、
結果は条件式になります。
条件は以下のように、他の要素間の関係演算子と論理演算子からなります。
演算 シンボル タイプ 小なり < 関係 中置 以下 <= 関係 中置 等号 (構文法的) = 関係 中置 不等号 (構文法的) # 関係 中置 等号 (値) equal 関係 関数 不等号 (値) notequal 関係 関数 以上 >= 関係 中置 大なり > 関係 中置 かつ and 論理 中置 または or 論理 中置 否定 not 論理 前置
map
は、主演算子(訳注:内部表現の最上位階層のリストに対応する演算子)は
式expr_1, ..., expr_nのそれと同じ演算子を使い、
そのサブパーツは、引数式の対応するサブパーツにfを適用した結果である式を返します。
fはn個の引数の関数名か、n個の引数のラムダ形式です。
(訳注:また、expr_1, …, expr_nは内部表現に階層リスト構造を持つ式です。)
maperror
- もしmaperror
がfals
eなら、
マッピング関数のすべては、(1)もしexpr_iのすべてが同じ長さでなければ、
最も短いexpr_iが完了した時点で停止し、
(2)もしexpr_iが同じタイプのオブジェクトでなければ、
fをリスト[expr_1, expr_2, ...]に適用します。
もしmaperror
がtrue
なら、上の2つの場合、エラーメッセージを出力します。
この関数の用法の1つは、ある関数(例えば、partfrac
)を非常に長い式に適用する際、
計算の間にリスト保存領域を枯渇させるため式全体に適応するのが不可能な場合に、
それぞれの項に関数をマップすることです。
(%i1) map(f,x+a*y+b*z); (%o1) f(b z) + f(a y) + f(x) (%i2) map(lambda([u],partfrac(u,x)),x+1/(x^3+4*x^2+5*x+2)); 1 1 1 (%o2) ----- - ----- + -------- + x x + 2 x + 1 2 (x + 1) (%i3) map(ratsimp, x/(x^2+x)+(y^2+y)/y); 1 (%o3) y + ----- + 1 x + 1 (%i4) map("=",[a,b],[-0.5,3]); (%o4) [a = - 0.5, b = 3]
exprがマップルーチンでアトムとして扱われる時だけtrue
を返します。
"Mapatoms"はアトム、(有理数を含む)数、添字付き変数です。
デフォルト値: true
maperror
がfalse
の時は、
マップ関数すべてに、以下の例のようにさせます。
map (f, expr_1, expr_2, …)
に対しては、 (1) もしexpr_iのすべてが同じ長さでないなら、 最も短いexpr_iの終わりまで完了した時、停止するようにさせ、 (2) もしexpr_iすべてが同じタイプのオブジェクトでないなら、 fを[expr_1, expr_2, ...]に適用するようにさせます。
もしmaperror
がtrue
なら、
上の2つの例に関して、エラーメッセージが表示されます。
デフォルト値: true
mapprint
がtrue
の時、
map
, mapl
, fullmap
からの様々な情報メッセージが
一定の状況で生成されます。
これらは
map
がapply
を使ったり、map
が
最短のリストで切り詰めているような状況を含みます。
もしmapprint
がfalse
なら、これらのメッセージは抑制されます
式expr_1, …, expr_nのパーツにfを適用した結果のリストを返します。 fは、関数名かラムダ式です。
maplist
はmap (f, expr_1, ..., expr_n)
とは違います。
mapは主演算子がexpr_iと同じ式を返します。
(整理とmap
がapply
を行う場合は例外です。)
デフォルト値: false
prederror
がtrue
の時、
if
文の述語論理かis
関数が
true
かfalse
に評価されるのに失敗した時はいつでも
エラーメッセージが表示されます。
もしfalse
なら、この場合,代わりにunknown
が返されます。
prederror: false
モードは翻訳コードではサポートされません;
しかしながら、maybe
は翻訳コードでサポートされます。
is
とmaybe
も参照してください。
引数を連れて、陽にブロックから抜けるために使われます。
もっと情報を知るには、block
も参照してください。
トップダウン法で、fをexprに再帰的に適用します。 完全な因数分解が望まれる時、これは最も役に立ちます。 例えば:
(%i1) exp:(a^2+2*a+1)*y + x^2$ (%i2) scanmap(factor,exp); 2 2 (%o2) (a + 1) y + x
Note the way in which
scanmap
が与えられた関数factor
を
exprの構成部分式に適用する方法に注意してください;
もし
exprの別の形がscanmapに適用されるなら、結果は異なるかもしれません。
従って、
scanmap
が
exp
の展開形に適用される時、
%o2
が再現されません:
(%i3) scanmap(factor,expand(exp)); 2 2 (%o3) a y + 2 a y + y + x
scanmap
が
与えられた関数を指数関数を含む部分式すべてに再帰的に適用する方法の別の例です:
(%i4) expr : u*v^(a*x+b) + c$ (%i5) scanmap('f, expr); f(f(f(a) f(x)) + f(b)) (%o5) f(f(f(u) f(f(v) )) + f(c))
scanmap (f, expr, bottomup)
は、
ボトムアップ法で
fを
exprに適用します。
例えば、未定義f
に関して、
scanmap(f,a*x+b) -> f(a*x+b) -> f(f(a*x)+f(b)) -> f(f(f(a)*f(x))+f(b)) scanmap(f,a*x+b,bottomup) -> f(a)*f(x)+f(b) -> f(f(a)*f(x))+f(b) -> f(f(f(a)*f(x))+f(b))
この場合、両方の方法で同じ答えを得ます。
exprを評価し、
直近のcatch
に値を投げ戻します。
throw
は、
catch
と一緒に、非ローカルリターンメカニズムとして使われます。
関数fを 外積a_1掛けるa_2 ... 掛けるa_nの要素のそれぞれに適用します。
fは n個の引数の関数の名前か、 n個の引数のラムダ式 です。
それぞれの引数a_kは、 リストか、入れ子のリストか、行列か、他の任意の種類の式を取り得ます。
outermap
戻り値は、入れ子の構造です。
xを戻り値とします。
すると、
xは最初のリストか入れ子のリストか行列引数と同じ構造を持ち、
x[i_1]...[i_m]
は、
二番目のリストか入れ子のリストか行列引数と同じ構造を持ち、
x[i_1]...[i_m][j_1]...[j_n]
は、
三番目のリストか入れ子のリストか行列引数と同じ構造を持ち、
以下同様。
ここで、m, n, ...は、
引数それぞれの要素
をアクセスするために要求される
インデックスの数(リストには1つ、行列には2つ、入れ子のリストには1つ以上)です。
リストや行列でない引数は戻り値の構造に影響を与えません。
Note that the effect of
outermap
の効果は
fを
cartesian_product
によって返される
外積の要素のそれぞれに適用することのそれと違います。
outermap
は、戻り値で引数の構造を保ちますが、
cartesian_product
は違います。
outermap
は引数を評価します。
map
, maplist
, apply
も参照してください。
例:
outermap
の初等的な例。
よりはっきり引数の組み合わせを示すために、
F
は未定義のままです。
(%i1) outermap(F, [a, b, c], [1, 2, 3]); (%o1) [[F(a, 1), F(a, 2), F(a, 3)], [F(b, 1), F(b, 2), F(b, 3)], [F(c, 1), F(c, 2), F(c, 3)]] (%i2) outermap(F, matrix([a, b],[c, d]), matrix([1, 2],[3, 4])); [ [ F(a, 1) F(a, 2) ] [ F(b, 1) F(b, 2) ] ] [ [ ] [ ] ] [ [ F(a, 3) F(a, 4) ] [ F(b, 3) F(b, 4) ] ] (%o2) [ ] [ [ F(c, 1) F(c, 2) ] [ F(d, 1) F(d, 2) ] ] [ [ ] [ ] ] [ [ F(c, 3) F(c, 4) ] [ F(d, 3) F(d, 4) ] ] (%i3) outermap (F, [a, b], x, matrix ([1, 2], [3, 4])); [ F(a, x, 1) F(a, x, 2) ] [ F(b, x, 1) F(b, x, 2) ] (%o3) [[ ], [ ]] [ F(a, x, 3) F(a, x, 4) ] [ F(b, x, 3) F(b, x, 4) ] (%i4) outermap (F, [a, b], matrix ([1, 2]), matrix ([x], [y])); [ [ F(a, 1, x) ] [ F(a, 2, x) ] ] (%o4) [[ [ ] [ ] ], [ [ F(a, 1, y) ] [ F(a, 2, y) ] ] [ [ F(b, 1, x) ] [ F(b, 2, x) ] ] [ [ ] [ ] ]] [ [ F(b, 1, y) ] [ F(b, 2, y) ] ] (%i5) outermap ("+", [a, b, c], [1, 2, 3]); (%o5) [[a + 1, a + 2, a + 3], [b + 1, b + 2, b + 3], [c + 1, c + 2, c + 3]]
outermap
の戻り値のより密な検査。
最初の、二番目の、三番目の引数は、それぞれ、行列、リスト、行列です。
戻り値は行列です。
その行列の要素それぞれはリストで、
それぞれのリストの要素それぞれは行列です。
(%i1) arg_1 : matrix ([a, b], [c, d]); [ a b ] (%o1) [ ] [ c d ] (%i2) arg_2 : [11, 22]; (%o2) [11, 22] (%i3) arg_3 : matrix ([xx, yy]); (%o3) [ xx yy ] (%i4) xx_0 : outermap(lambda([x, y, z], x / y + z), arg_1, arg_2, arg_3); [ [ a a ] [ a a ] ] [ [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] ] [ [ 11 11 ] [ 22 22 ] ] (%o4) Col 1 = [ ] [ [ c c ] [ c c ] ] [ [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] ] [ [ 11 11 ] [ 22 22 ] ]
[ [ b b ] [ b b ] ] [ [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] ] [ [ 11 11 ] [ 22 22 ] ] Col 2 = [ ] [ [ d d ] [ d d ] ] [ [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] ] [ [ 11 11 ] [ 22 22 ] ]
(%i5) xx_1 : xx_0 [1][1]; [ a a ] [ a a ] (%o5) [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] [ 11 11 ] [ 22 22 ] (%i6) xx_2 : xx_0 [1][1] [1]; [ a a ] (%o6) [ xx + -- yy + -- ] [ 11 11 ] (%i7) xx_3 : xx_0 [1][1] [1] [1][1]; a (%o7) xx + -- 11 (%i8) [op (arg_1), op (arg_2), op (arg_3)]; (%o8) [matrix, [, matrix] (%i9) [op (xx_0), op (xx_1), op (xx_2)]; (%o9) [matrix, [, matrix]
outermap
は、戻り値の中で引数の構造を保持します。
cartesian_product
は保持しません。
(%i1) outermap (F, [a, b, c], [1, 2, 3]); (%o1) [[F(a, 1), F(a, 2), F(a, 3)], [F(b, 1), F(b, 2), F(b, 3)], [F(c, 1), F(c, 2), F(c, 3)]] (%i2) setify (flatten (%)); (%o2) {F(a, 1), F(a, 2), F(a, 3), F(b, 1), F(b, 2), F(b, 3), F(c, 1), F(c, 2), F(c, 3)} (%i3) map(lambda([L], apply(F, L)), cartesian_product({a, b, c}, {1, 2, 3})); (%o3) {F(a, 1), F(a, 2), F(a, 3), F(b, 1), F(b, 2), F(b, 3), F(c, 1), F(c, 2), F(c, 3)} (%i4) is (equal (%, %th (2))); (%o4) true
Next: Debugging, Previous: Function Definition [Contents][Index]