[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

37. Program Flow


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

37.1 Lisp and Maxima

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構成子は 対話プロンプトや batchdemoによって処理されるファイルの中で使えますが、 load, batchload, translate_file, compile_fileが処理するファイルの中では使えません。

関数 to_lisp()を実行すると 対話的な Lispセッションが始まります。 (to-maxima)を入力すると Lispセッションを終了して Maximaに戻ります。

Lispの関数や変数を、 Maximaで通常の関数名、変数名(特殊な句読点のない名前)に見せるには、 Lispの名前をドル記号 $で始めなければなりません。

Maximaでは識別子の中の大文字、小文字が区別されます。 Lispと Maximaの間の名前変換を決めるルールがあります。

  1. 縦棒で囲まれていない Lisp識別子は Maximaの小文字の識別子に対応します。 Lisp識別子が大文字でも小文字でも混ざっていても無視されます。 例えば Lispの $foo$FOO, $Fooはすべて Maximaのfooに対応します。 でも、これはデフォルトで、 Lispリーダが $foo, $FOO, $Fooを Lispシンボル $FOOに変換するからです。
  2. すべて大文字かすべて小文字で、縦棒で囲まれた Lisp識別子は、大文字小文字を逆にした Maximaの識別子に対応します。 例えば Lispの |$FOO|, |$foo|はそれぞれ Maximaの foo, FOOに対応します。
  3. 大文字小文字が混ざっていて、縦棒で囲まれた Lisp識別子は、そのまま Maximaの識別子に対応します。 例えば Lispの |$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

Categories:  Programming


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

37.2 Garbage Collection

数式処理は膨大なゴミ(最終的には使われない一時的な、もしくは中間の結果)を生む傾向があり、 ゴミの効率的な取り扱いは、プログラムをうまく完了させるために非常に重要な場合があります。

(SunOS 4.0やBSDの幾つかを含む) mprotectシステムコールが利用可能な UNIXシステム上での GCLでは、階層化 (stratified)ガーベッジコレクションが利用可能です。 これはガーベッジコレクションを最近書き込まれたページに限定します。 GCLドキュメントの ALLOCATEや GBCを参照してください。 Lispレベルで (setq si::*notify-gbc* t)を実行すると どの領域がより多くの空間を必要としているか決めるのに役立つでしょう。

Maximaを走らせる他の Lispについては、 その Lispの GCの制御の仕方に関するドキュメントを調べてください。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

37.3 Introduction to Program Flow

Maximaは goのようなもっとプリミティブな構成子はもちろん、繰り返しのために doループを提供します。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

37.4 Functions and Variables for Program Flow

関数: backtrace  
    backtrace ()  
    backtrace (n)

コールスタック、すなわち、現在アクティブな関数をコールした関数のリストを印字します。

backtrace()はコールスタック全体を印字します。

backtrace (n)は現在アクティブな関数を含めて n個の直近の関数を印字します。

backtraceは、(デバッグの文脈でだけでなく、) スクリプト、関数、対話プロンプトからコールすることができます。

例:

Categories:  Debugging

特殊演算子: do
特殊演算子: in

do文は繰り返しを実行するために使われます。 その強力な一般性のために do文は2編で記述されます。 最初、通常の形式が (Fortran, Algol, PL/I, など)いくつかの他のプログラミング言語の中で使われるそれ との類似で与えられます; それから他の特長が言及されます。

この形式の終了条件に関してだけ違う3つの別形があります。 それらは:

(代わりに stepは終了条件や範囲の後与えられるかもしれません。)

initial_value, increment, limit, bodyは任意の式を取り得ます。 もし増分が 1なら "step 1"は省略できます。

do文の実行は、最初 initial_valuevariable (今後、制御変数と呼びます) に割り当てることによって処理されます。 そして: (1) もし制御変数が thru指定の範囲を越えたら、もしくは、 unlessの条件が trueもしくは whileの条件が falseなら、 doは終了します。 (2) bodyが評価されます。 (3) 増分が制御変数に足されます。 終了条件が満たされるまで、いずれかが満たされる時 doが終了する複数の終了条件を与えることもできます。

一般的に、 thruテストは、 もし incrementが非負なら制御変数が limitよりも大きい時、 または、もし incrementが負なら制御変数が limitよりも小さい時、 満たされます。 incrementlimitはこの不等式が決定できる限り数値でない式も取り得ます。 しかし、 do文が入力された時 incrementが構文法的に負(例えば負の数)でない限り、 Maximaは doが実行される時、正と仮定します。 もし正でないなら doは適切に終了しないかもしれません。

limit, increment, 終了条件はループを通して毎回評価されることに注意してください。 もしこれらのいずれかが多くの計算を含み、 bodyの実行中すべてで変わらない結果をもたらすなら、 doに先立って変数をそれらの値に設定し、その変数を do形式の中で使うことはもっと効率的です。

do文が通常返す値はアトム doneです。 しかし、早い時点で doから抜けて任意の望みの値を与えるために、 関数 returnbodyの中で使うことができます。 しかし、 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 > 10thru 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 valuestepnext値の後や終了条件の後に置くことを許します。 もし 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だけを与えることもできます。 この場合、関数 returndoの実行を終了するのに使われるべきです。

 
(%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

Categories:  Programming

関数: errcatch (expr_1, …, expr_n)

expr_1, …, expr_nを1つずつ評価し、もしエラーが起こらないなら、 [expr_n] (リスト)を返します。 もしいずれかの引数の評価中にエラーが起こったら、 errcatch はエラーが伝搬することを抑制し、 引数をこれ以上評価せずに空のリスト []を返します。

errcatchは、もしエラーがチャッチされないなら batchを終了させるエラーが起こるかもしれないと疑うような batchファイルで役立ちます。

Categories:  Programming

関数: error (expr_1, ..., expr_n)
システム変数: error

expr_1, ..., expr_nを評価して印字します。 そしてエラーがあれば、トップレベル Maximaか直近の errcatchに戻るようにします。

変数 errorはエラーを記述するリストに設定されます。 errorの最初の要素はフォーマット文字列です。 引数 expr_1, ..., expr_nの中の文字列すべてを結合したものです。 残りの要素は文字列でない引数の値です。

errormsg()errorをフォーマットし印字します。 これは直近のエラーメッセージを効果的に再印字します。

Categories:  Programming

オプション変数: error_size

デフォルト値: 10

error_sizeは現れる式のサイズに従ってエラーメッセージを変更します。 もし( Lisp 関数 ERROR-SIZEが決定するような)式のサイズが error_sizeより大きいなら、 式はメッセージの中でシンボルで置き換えられ、シンボルは式に割り当てられます。 シンボルはリスト error_symsから取られます。

そうでないなら、式は error_sizeより小さくメッセージの中に式が表示されます。

errorerror_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);

オプション変数: error_syms

デフォルト値: [errexp1, errexp2, errexp3]

エラーメッセージの中で、 error_sizeより大きな式はシンボルで置き換えられ、シンボルは式に設定されます。 シンボルはリスト error_symsから取られます。 最初の大きすぎる式は error_syms[1]で置き換えられ、 2番目は error_syms[2]で置き換えられ、と続きます。

もし大きすぎる式が error_symsの要素よりもたくさんあるなら シンボルは自動的に構成されます。 n番目のシンボルは concat ('errexp, n)と同値です。

errorerror_sizeも参照してください。

関数: errormsg ()

直近のエラーメッセージを再印字します。 変数 errorはメッセージを保持し、 errormsgはそれをフォーマットし印字します。

Categories:  Programming

オプション変数: errormsg

デフォルト値: true

falseの時、エラーメッセージの出力は抑制されます。

オプション変数 errormsgは ブロックの中でローカル値に設定することはできません。 errormsgのグローバル値が常に存在します。

 
(%i1) errormsg;
(%o1)                         true
(%i2) sin(a,b);
sin: wrong number of arguments.
 -- 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

Categories:  Programming

特殊演算子: for

繰り返しで使われます。 Maximaの繰り返し機能の記述に関しては doを参照してください。

Categories:  Programming

関数: go (tag)

制御を goの引数でタグ付けされたブロックの文に移すために block内部で使われます。 文をタグ付けするには、その文の前にアトムの引数を blockの中の別の文として先行させてください。 例えば:

 
block ([x], x:1, loop, x+1, ..., go(loop), ...)

goの引数は同じ blockの中に現れるタグの名前でなければいけません。 goを含む block以外の blockの中のタグに移るために、 goを使うことはできません。

Categories:  Programming

特殊演算子: if

条件評価を表します。 if式の様々な形が認識されます。

if cond_1 then expr_1 else expr_0は、もし cond_1true評価されたら expr_1に*評*価*され、 そうでないなら式は expr_0に評価されます。

コマンド if cond_1 then expr_1 elseif cond_2 then expr_2 elseif ... else expr_0は、 もし cond_ktrueでかつ先行する条件がすべて falseなら、 expr_kに評価されます。 もし条件のいずれも trueでないなら式は expr_0に評価されます。

もし elseがないなら、 最後に else falseが仮定されます。 すなわち、コマンド if cond_1 then expr_1if cond_1 then expr_1 else falseと同値で、 コマンド if cond_1 then expr_1 elseif ... elseif cond_n then expr_nif 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は、潜在的に、また、実際に truefalseに評価される式です。 条件が実際には trueにも falseにも評価されない時、 ifの振る舞いはグローバルフラグ prederrorで決定されます。 prederrortrueの時、 もし評価された条件のいずれかが trueにも falseにもならなかったら、エラーになります。 そうでないなら、 trueにも falseにも評価されない条件が受け入れられ、 結果は条件式になります。

条件は以下のように他の要素間の関係演算子と論理演算子からなります。

 
演算                 シンボル     タイプ

小なり                <           関係 中置
以下                  <=          関係 中置
等号 (構文法的)        =           関係 中置
不等号 (構文法的)      #           関係 中置
等号 (値)             equal       関係 関数
不等号 (値)           notequal    関係 関数
以上                  >=          関係 中置
大なり                >           関係 中置
かつ                  and         論理 中置
または                or          論理 中置
否定                  not         論理 前置

Categories:  Programming · Predicate functions

関数: map (f, expr_1, …, expr_n)

mapは、主演算子(訳注:内部表現の最上位階層のリストに対応する演算子)は式 expr_1, ..., expr_nのそれと同じ演算子を使い、 そのサブパーツは、引数式の対応するサブパーツに fを適用した結果である式を返します。 fn個の引数の関数名か n個の引数のラムダ形式です。 (訳注:また expr_1, …, expr_nは内部表現に階層リスト構造を持つ式です。)

maperror - もし maperrorfalseなら、 マッピング関数のすべては、(1)もし expr_iのすべてが同じ長さでなければ、 最も短い expr_iが完了した時点で停止し、 (2)もし expr_iが同じタイプのオブジェクトでなければ、 fをリスト [expr_1, expr_2, ...]に適用します。 もし maperrortrueなら、上の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]


Categories:  Function application

関数: mapatom (expr)

exprがマップルーチンでアトムとして扱われる時だけ trueを返します。 "Mapatoms"はアトム、(有理数を含む)数、添字付き変数です。

Categories:  Predicate functions

オプション変数: maperror

デフォルト値: true

maperrorfalseの時は、 マップ関数すべてに以下の例のようにさせます。

 
map (f, expr_1, expr_2, …)

に対しては、 (1) もし expr_iのすべてが同じ長さでないなら、 最も短い expr_iの終わりまで完了した時、停止するようにさせ、 (2) もし expr_iすべてが同じタイプのオブジェクトでないなら、 fを [expr_1, expr_2, ...]に適用するようにさせます。

もし maperrortrueなら、 上の2つの例に関してエラーメッセージが表示されます。

Categories:  Function application

オプション変数: mapprint

デフォルト値: true

mapprinttrueの時、 map, maplist, fullmapからの様々な情報メッセージが 一定の状況で生成されます。 これらは mapapplyを使ったり、 mapが最短のリストで切り詰めているような状況を含みます。

もし mapprintfalseなら、これらのメッセージは抑制されます

Categories:  Function application

関数: maplist (f, expr_1, …, expr_n)

expr_1, …, expr_nのパーツに fを適用した結果のリストを返します。 fは関数名かラムダ式です。

maplistmap (f, expr_1, ..., expr_n)とは違います。 mapは主演算子が expr_iと同じ式を返します。 (整理と mapapplyを行う場合は例外です。)

Categories:  Function application

オプション変数: prederror

デフォルト値: false

prederrortrueの時、 if文の述語論理か is関数が truefalseに評価されるのに失敗した時はいつでも エラーメッセージが表示されます。

もし falseなら、この場合,代わりに unknownが返されます。 prederror: falseモードは翻訳コードではサポートされません; しかし、 maybeは翻訳コードでサポートされます。

ismaybeも参照してください。

Categories:  Programming · Predicate functions

関数: return (value)

引数を連れて、明示的に現在の block, while, for, doループから抜けるために使われます。 なので他のプログラミング言語にある return文と比較できますが、1つ違いがあります: maximaでは、呼ばれた関数全体からではなく現在のブロックから戻るだけです、 この観点では、Cの break文とより似ています。

 
(%i1) for i:1 thru 10 do o:i;
(%o1)                         done
(%i2) for i:1 thru 10 do if i=3 then return(i);
(%o2)                           3
(%i3) for i:1 thru 10 do
    (
        block([i],
            i:3,
            return(i)
        ),
        return(8)
    );
(%o3)                           8
(%i4) block([i],
    i:4,
    block([o],
        o:5,
        return(o)
    ),
    return(i),
    return(10)
 );
(%o4)                           4

for, while, do, blockも参照してください。

Categories:  Programming

関数: scanmap  
    scanmap (f, expr)  
    scanmap (f, expr, bottomup)

トップダウン法で fexprに再帰的に適用します。 完全な因数分解が望まれる時、これは最も役に立ちます。 例えば:

 
(%i1) exp:(a^2+2*a+1)*y + x^2$
(%i2) scanmap(factor,exp);
                                    2      2
(%o2)                         (a + 1)  y + x

scanmapが与えられた関数 factorexprの構成部分式に適用する方法に注意してください; もし exprの別の形が scanmapに適用されるなら、結果は異なるかもしれません。 従って、 scanmapexpの展開形に適用される時、 %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)は、 ボトムアップ法で fexprに適用します。 例えば、未定義 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))

この場合、両方の方法で同じ答えを得ます。

Categories:  Function application

関数: throw (expr)

exprを評価し、直近の catchに値を投げ戻します。 throwcatchと一緒に非ローカルリターンメカニズムとして使われます。

Categories:  Programming

特殊演算子: while
特殊演算子: unless

doを参照してください。

Categories:  Programming

関数: outermap (f, a_1, …, a_n)

関数 fを外積 a_1掛ける a_2 ... 掛ける a_nの要素のそれぞれに適用します。

fn個の引数の関数の名前か、 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つ以上)です。 リストや行列でない引数は戻り値の構造に影響を与えません。

outermapの効果は cartesian_productが返す外積の要素のそれぞれに fを適用することのそれと違うことに注意してください。 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

Categories:  Function application


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by 市川雄二 on June, 21 2016 using texi2html 1.76.