[ < ] | [ > ] |  | [ << ] | [上] | [ >> ] |  |  |  |  | [冒頭] | [目次] | [見出し] | [ ? ]

# 37. Program Flow

[ < ] | [ > ] |  | [ << ] | [上] | [ >> ] |  |  |  |  | [冒頭] | [目次] | [見出し] | [ ? ]

## 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`を使って、 （１つか複数のフォームを含む） 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の間の名前変換を決めるルールがあります。

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

[ < ] | [ > ] |  | [ << ] | [上] | [ >> ] |  |  |  |  | [冒頭] | [目次] | [見出し] | [ ? ]

## 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の制御の仕方に関するドキュメントを調べてください。

[ < ] | [ > ] |  | [ << ] | [上] | [ >> ] |  |  |  |  | [冒頭] | [目次] | [見出し] | [ ? ]

## 37.3 Introduction to Program Flow

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

[ < ] | [ > ] |  | [ << ] | [上] | [ >> ] |  |  |  |  | [冒頭] | [目次] | [見出し] | [ ? ]

## 37.4 Functions and Variables for Program Flow

関数: backtrace ()
関数: backtrace (n)

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

  `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

  ·

  Categories: Debugging

特殊演算子: do

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

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

  - `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`のもう１つ別の形式が 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を１つずつ評価し、もしエラーが起こらないなら、 `[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`より小さくメッセージの中に式が表示されます。

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

  ·

  Categories: Debugging ·Display flags and variables

オプション変数: error_syms

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

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

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

  `error`と `error_size`も参照してください。

  ·

  Categories: Debugging ·Display flags and variables

関数: errormsg ()

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

  ·

  Categories: Programming

オプション変数: 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

  ·

  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_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         論理 前置

  ·

  Categories: Programming ·Predicate functions

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

  `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`なら、上の２つの場合、エラーメッセージを出力します。

  この関数の用法の１つは、ある関数（例えば `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`

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

      map (f, expr_1, expr_2, …)

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

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

  ·

  Categories: Function application

オプション変数: mapprint

  デフォルト値: `true`

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

  もし `mapprint`が `false`なら、これらのメッセージは抑制されます

  ·

  Categories: Function application

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

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

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

  ·

  Categories: Function application

オプション変数: prederror

  デフォルト値: `false`

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

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

  `is`と `maybe`も参照してください。

  ·

  Categories: Programming ·Predicate functions

関数: return (value)

  引数を連れて、明示的にブロックから抜けるために使われます。 もっと情報を知るには `block`も参照してください。

  ·

  Categories: Programming

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

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

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

  `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))

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

  ·

  Categories: Function application

関数: throw (expr)

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

  ·

  Categories: Programming

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

  `do`を参照してください。

  ·

  Categories: Programming

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

  関数 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, ...は、 引数それぞれの要素をアクセスするために要求されるインデックスの数 (リストには１つ、行列には２つ、入れ子のリストには１つ以上)です。 リストや行列でない引数は戻り値の構造に影響を与えません。

  `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

[ << ] | [ >> ] |  |  |  |  |  | [冒頭] | [目次] | [見出し] | [ ? ]

この文書は市川 雄二によって2012年12月月12日にtexi2html 1.82を用いて生成されました。