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

9. プログラムの流れ

9.1 プログラムの流れについて  
9.2 プログラムの流れに関する諸定義  


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

9.1 プログラムの流れについて

MACSYMAには反復処理にDOループとGOと云ったより原始的な構造もある。


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

9.2 プログラムの流れに関する諸定義

変数: BACKTRACE
デフォルト値:[] - (DEBUGMODE:ALLとなっている時)現時点で入力された関数 全てのリストを値として持つ。

特殊演算子: DO
- DO文は繰り返しの実行に使う。その広汎な一般性からDO文は二つの事項について 記述される。第一のものは通常の書式として与えられるもので、幾つかの他の プログラム言語(FORTRAN、ALGOL、PL/I等)で利用されるものと類似している。 そこで他の機能について述べる事とする。

1. 三種類の変種があり、各々は終了条件のみ異なる。

(STEPは終了条件や境界の後に置いても良い。)

初期値、増分、境界と本体は如何なる式でも良い。増分が1であれば、"STEP 1"は 省略しても良い。

DO文の実行は最初に初期値を変数に割当てる(それ故、その変数を制御変数と呼ぶ)。

その終了条件が満される迄、(1)から(3)までの処理が繰り返し実行される。幾つか の終了条件も与えても良く、その場合は、それらの内のどれか一つでも条件を満した 時にDO文が終了する。

一般的に、THRUテストを満足させるのは、増分が非負であれば制御変数がその境界値 よりも大きくなった時、増分が負であれば制御変数がその境界値よりも小さくなった 時である。増分と境界は不等号が判別可能でさえあれば非数値式であっても構わない。 しかし、DO文が入力された時に、増分が構文的に負(例えば負の数)でない限り、 MACSYMAはDO文を実行する時にそれが正であると仮定する。もし、それが正でなければ、 DO文を正しく終了する事が出来ない。

境界値、増分と終了条件はループの間の各時点で評価される事に注意する。それ故、 これらの任意のものが膨大な計算を引き起すものの、その一方で、生成された結果が 本体全ての実行の間に変化しないものであれば、DO文に対して効果的な値を変数に 設定して、この変数をDO文で用いるのがより効率的である。

通常DO文によって返される変数は原子のDONEであり、MACSYMAで全ての文が返す値と 同じである。ここで、関数RETURNは本体の中でDOから早目に抜けて任意の必要な値を 与える為に用いて良い。しかし、BLOCKにあるDO文中のRETURNはDO文を出るだけで、 BLOCKから出る訳では無い事に注意せよ。更に、GO関数もBLOCK中のDO文から抜ける為 に使ってはならない事に注意せよ。

制御変数はDO文に対して常に局所的であり、それ故、任意の変数はDO文の外側と同名 の変数の値に影響を与えずに利用する事が可能である。制御変数はDO文が終了した後 に不定値になる。

 
(C1)   FOR A:-3 THRU 26 STEP 7 DO LDISPLAY(A)$
(E1)          A = -3
(E2)          A =  4
(E3)          A = 11
(E4)          A = 18
(E5)          A = 25

関数LDISPLAYはこの様に中間ラベルを生成する;しかし、DISPLAYはそうでは無い。

 
(C6)   S:0$
(C7)   FOR I:1 WHILE I<=10 DO S:S+I;
(D7)          DONE
(C8)   S;
(D8)          55

C7での条件はUNLESS I>10やTHRU 10とも同値である事に注意せよ。

 
(C9)   SERIES:1$
(C10)  TERM:EXP(SIN(X))$
(C11)  FOR P:1 UNLESS P>7 DO
          (TERM:DIFF(TERM,X)/P,
          SERIES:SERIES+SUBST(X=0,TERM)*X^P)$
(C12)   SERIES;
                7    6     5    4    2
(D12)          X    X     X    X    X
               -- - --- - -- - -- + -- + X + 1
               96   240   15   8    2

上の例ではe^sin(x)のTaylor級数の8個の項を与えている。

(C13) POLY:0$
(C14) FOR I:1 THRU 5 DO
        FOR J:I STEP -1 THRU 1 DO
           POLY:POLY+I*X^J$
(C15) POLY;
              5      4       3       2
(D15)      5 X  + 9 X  + 12 X  + 14 X  + 15 X
(C16) GUESS:-3.0$
(C17) FOR I:1 THRU 10 DO (GUESS:SUBST(GUESS,X,.5*(X+10/X)),
         IF ABS(GUESS^2-10)<.00005 THEN RETURN(GUESS));
(D17)                  - 3.1622807

この上の例では10の負の平方根をNewton-Raphson法を用いて最大10回の反復計算を 行っている。収束判定で値が見付からなければ"DONE"を返すものである。

DO文の追加形式

制御変数に対して何時も加える量の代りに、各々の反復で別の手法に代えたい事もあ るだろう。この場合、"NEXT式"を"STEP増分"の代りに用いて良い。これで制御変数に はループを通して各時点で式を評価した値が設定される。

 
(C1)  FOR COUNT:2 NEXT 3*COUNT THRU 20
         DO DISPLAY(COUNT)$
                    COUNT = 2
                    COUNT = 6
                    COUNT = 18

FOR 変数:値 ... DO ...構文の代りに、FOR 変数 FROM 値 ... DO ...が使える。 "FROM 値"をSTEPやNEXTの値や終了条件の後に置く事も可能である。"FROM 値"が省略 されると1が初期値として用いられる。

時には反復処理の実行で、制御変数が実際に使われていないものに興味を持つかもし れない。そこで、終了条件のみに情報の初期化と更新を、次の貧弱な初期推定値を用 いて5の平方根を計算する次の例の様に省略する事も可能である。
 
(C1) X:1000
(C2)  THRU 10 WHILE X#0.0 DO X:.5*(X+5.0/X)$
(C3) X;
(D3)               2.236068

もし、望ましければ、終了条件でさえもすっかり省略し、不定値のまま本体を評価し 続ける"DO 本体"を与えて良い。この場合、RETURN関数をDO文の実行を中断する為に 用いなければならない。
 
(C1) NEWTON(F,GUESS):=
  BLOCK([NUMER,Y],
        LOCAL(DF),
        NUMER:TRUE,
        DEFINE(DF(X),DIFF(F(X),X)),
        DO (Y:DF(GUESS),
            IF Y=0.0 THEN ERROR("Derivative at:",GUESS," is zero."),
            GUESS:GUESS-F(GUESS)/Y,
            IF ABS(F(GUESS))<5.0E-6 THEN RETURN(GUESS)))$
(C2) SQR(X):=X^2-5.0$
(C3) NEWTON(SQR,1000);
(D3)                    2.236068

(RETURNが実行された時、GUESSの現行の値がDO文の値として返される事に注意せよ。 BLOCKから抜けるとDO文の値はBLOCKの値として返される。何故なら、 DOはBLOCKの 中で最後の文の為である)。

DO文のもう一方の形式がMACSYMAで利用可能である。その構文は:
 
FOR 変数 IN リスト [end-tests] DO 本体
である。

リストの成分は任意の式であり、本体の各反復では変数に続けて割り当てられる。 オプションのend-testsはDO文の実行を終了させる為に用いる事が可能で、さもなくば、 リストを消耗した時や本体でRETURNが実行された時に終了する(実際、リストは任意の 原子でない式や連続した成分が取られていても良い)。

 
(C1)  FOR F IN [LOG, RHO, ATAN] DO LDISP(F(1))$
(E1)                                  0
(E2)                                RHO(1)
                                     %PI
(E3)                                 ---
                                      4
(C4) EV(E3,NUMER);
(D4)                             0.78539816

関数: ERRCATCH (exp1, exp2, ...)
引数を一つづつ評価して、エラーが生じなければ最後の値のリストを返す。もし、 任意の引数の評価でエラーが生じた場合、ERRCATCHはエラーを"捉え(catches)"て 即座に[](空のリスト)を返す。この関数はエラーが生じていると疑われるBATCH ファイルで、エラーを捉えなければ怱ちBATCHを終了させる様にすると便利である。

変数: ERREXP
デフォルト値:[ERREXP] 計算の過程でエラーが生じた時、MACSYMAはエラーメッセージ を表示して計算を終了する。ERREXPに問題が生じた式が設定され、メッセージ "ERREXPR contains the offending expression"(ERREXPRに問題が生じた式が含まれて います)と云うメッセージを表示する。そこで利用者がERREXP;と入力すれば、これを 見て幸運であれば、その問題点を見付ける事が出来る。

関数: ERROR (arg1, arg2, ...)
その引数の評価と表示を行い、そうして、MACSYMAのトップレベルか、最も近い ERRCATCHにエラーを返す。エラー条件を検知した場合や、control-^が入力出来ない 場所なら何処でも入れ子の関数を中断させるので便利である。変数ERRORはエラーを 記述するリストが設定されており、最初のものはテキスト文字列で、残りの オブジェクトは問題のものである。

ERRORMSG();は最近のエラーメッセージを見せる適切な方法である。

ERRORFUN デフォルト値: [FALSE] - エラーが発生すると何時でも実行される引数を 持たない関数の名前を設定する。これはBATCHファイルでエラーが生じた場合、 MACSYMAを殺したり、端末からログアウトしたい時に便利である。

変数: ERRORFUN
デフォルト値[FALSE] - 引数を持たない関数の名前が設定されていれば、その関数が エラーが発生すると何時も実行される事になる。これはBATCHファイルで便利であり、 エラーが生じた場合に利用者がMACSYMAを殺したり、端末からログアウトしたい時に 使える。

関数: ERRORMSG ()
最新のエラーメッセージを再表示する。表示端末を用いていてメッセージが画面から 消え去った時に、とても便利なものである。変数ERRORには問題のエラーを記した リストが設定されており、最初はテキストの文字列で、残りは問題のオブジェクト である。

TTYINTFUN:LAMBDA([],ERRORMSG(),PRINT(""))$ で利用者中断文字(^U)を メッセージの再表示を行う様に設定する。

特殊演算子: FOR
- 反復処理にて用いられる。MACSYMAの反復処理の機能の詳細はDESCRIBE("DO");を 実行せよ。

関数: GO (tag)
BLOCK内部で、GOの引数でタグ(tag:札)で指定したBLOCKの文に制御を移動するのに 用いられる。文をタグで指定する為、BLOCKの中の他の文の様に原子引数をその文の 前に置く。

例えば:
 
BLOCK([X],X:1,LOOP,X+1,...,GO(LOOP),...)
GOの引数は同じBLOCKの中で現われる札名でなければならない。GOを含む別のBLOCK にある札にGOを用いて移動する事は出来ない。

特殊演算子: IF
- IF文は条件分岐に用いる。その構文は:
 
    IF 条件 THEN 式1 ELSE 式2
IF文の結果は、条件がTRUEであれば式1、FALSEであれば式2となる。式1と式2は任意の MACSYMAの式(IF文の入れ子も含む)で、条件はTRUEかFALSEかを評価される式や関係と 論理的演算子で構成されたものであり、ここで論理演算子は以下の様なものである:

 
 
演算子名            記号        種類
よりも大きい        >           関係を記述する中置詞(infix)
に等しい            = , EQUAL   "  "
に等しくない        #           "  "
よりも小さい        <           "  "
より以上            >=          "  "
より以下           <=           "  "
and                 AND         論理中置詞(infix)
又は                OR          "  "
否定                NOT         論理前置詞(PREFIX)
(* 訳者注
前置詞(PREFIX)と中置詞(INFIX)は演算子を、その引数の置き方で区分したもの。
前置詞(PREFIX):OP <-> OP X    (e.g. NOT X=1,...)
中置詞(INFIX): OP <-> X OP Y  (e.g. X=Y,X*Y,...)
詳細は前置詞(PREFIX)と中置詞(INFIX)の項目を参照せよ。
*)

関数: LISPDEBUGMODE ()
LISPDEBUGMODE(); DEBUGPRINTMODE(); and DEBUG(); 利用者に対し、システムプログラマーが用いる虫取り機能を使える様にする。 これらのツールは強力で、しかも、幾つかの操作方法が通常のMascymaの階層と違って いるが、それらの利用はとても直接的と感じるだろう。[幾つかの表示は遅い端末では 冗長かもしれないが、これを制御するスイッチがある]。これらの命令は変換された Macsymaのコードを虫取りしなければならない利用者向けに設計されている。 より詳細はMACDOC;TRDEBG USAGEを見よ。より多くのHelpは、GJCに相談せよ。

関数: MAP (fn, exp1, exp2, ...)
式を返す。その式の先頭の演算子はepxiのものと同じで、その部分成分はexpiの部分 成分に対してfnを作用させた結果となる。fnはn個の引数(ここでnはexpiの数)の関数 の名前か、n個の引数のLAMBDA形式となる。

MAPERROR[TRUE] - FALSEであれば、全てのMAP関数は

となる。

MAPERRORがTRUEであれば、上記の状態でエラーメッセージを出す。この関数の利用 目的の一つが関数(例えば、PARTFRAC)を非常に大きな式の各項に写像する事であり、 その式は計算の過程でリストの保管場所を消耗する為、関数を式全体に用いる事には 適さないものである。

 
(C1) MAP(F,X+A*Y+B*Z);
(D1)                        F(B Z) + F(A Y) + F(X)
(C2) MAP(LAMBDA([U],PARTFRAC(U,X)),X+1/(X^3+4*X^2+5*X+2));
                           1       1        1
(D2)                     ----- - ----- + -------- + X
                         X + 2   X + 1          2
                                         (X + 1)
(C3) MAP(RATSIMP, X/(X^2+X)+(Y^2+Y)/Y);
                                      1
(D3)                            Y + ----- + 1
                                    X + 1
(C4) MAP("=",[A,B],[-0.5,3]);
(D4)                          [A = - 0.5, B = 3]


関数: MAPATOM (expr)
exprがMAPルーチンによって1単位が"原子"として扱われる時、TRUEとなる。 "Mapatoms"は原子、数(有理数を含む)と下添字された変数である。

変数: MAPERROR
デフォルト値:[TRUE] - FALSEであれば、全てのMAP関数は例えば以下の様になる。
 
MAP(fn,exp1,exp2,...))

MAPERRORがTRUEの場合、上の二つの状況であればエラーメッセージが出力される。

関数: MAPLIST (fn, exp1, exp2, ...)
expiの部分に対するfnの作用のリストを生成する。これは同じ主演算子を持つ式を返す MAP(fn,exp1,exp2,...)とは異なる。expiが持っている(簡易化の為とMAPがAPPLYを実行 する場合を除いて)とは異なる。fnはMAPのものと同じ形式である。

変数: PREDERROR
デフォルト値:[TRUE] - TRUEであれば、IF文やIS関数がTRUEかFALSEかの評価に失敗 した時には何時でも、エラーメッセージが表示される。FALSEであれば、この場合は UNKNOWNが代りに返される。PREDERROR:FALSEモードは移植されたコードでは提供され ていない。

関数: RETURN (value)
BLOCKからその引数を伴って抜ける為に用いても良い。詳細はDESCRIBE(BLOCK); を実行せよ。

関数: SCANMAP (function,exp)
再帰的に関数を"トップダウン"方式でexpに適用する。これは"徹底した"因子分解が 望ましい時には特に便利である。

 
例えば:

(C1) EXP:(A^2+2*A+1)*Y + X^2$
(C2) SCANMAP(FACTOR,EXP);
                                    2      2
(D2)                         (A + 1)  Y + X

ここでSCANMAPは与えられたFACTOR関数をexpに含まれる部分式に作用させる; もし、expの別の形式がSCANMAPに対して表現されていれば、結果が異なるかもしれ ない事に注意せよ。それ故、SCANMAPをexpの展開した形式に適用してもD2が修復され ない。

 
(C3) SCANMAP(FACTOR,EXPAND(EXP));
                           2                  2
(D3)                      A  Y + 2 A Y + Y + X

以下に別の例があり、そこではSCANMAPが指数を含めた全ての部分式に対して与えら れた関数を再帰的に適用する。

 
(C4) EXPR : U*V^(A*X+B) + C$
(C5) SCANMAP('F, EXPR);
                    F(F(F(A) F(X)) + F(B))
(D5) F(F(F(U) F(F(V)                      )) + F(C))

SCANMAP(function,expression,BOTTOMUP)は、例えば、Fが未定義であれば、 "ボトムアップ"式にfunctionをexpに作用させる。

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

この場合、同様の答を両方の方法で得る。

関数: THROW (exp)
expを評価し、最も最近のCATCHに値を投げ返す。THROWはCATCHと一緒に構造化された 非局所的な脱出機構として用いられる。


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

This document was generated by Hiroshi Yokota on September, 16 2002 using texi2html