Contents Previous Next Index
|
9 基本的なプログラミング
|
|
ここまでの章では、1 つのコマンドを実行するなどの操作を順番に、対話的に実行する方法を説明しました。Maple は完全なプログラミング言語であるため、高度なプログラミング構造を使用することもできます。
Maple では、プロシージャと呼ばれるプログラムを書き、モジュールに保存することができます。このモジュールは、Maple パッケージと同様に使用したり、配布したりすることができます。
重要 : プログラミング時またはプログラミングコマンドの使用時には、ワークシートモードおよび 1-D Math 入力を使用することを強くお勧めします。したがって、この章のすべての入力は 1-D Math として入力されています。
|
9.2 フロー制御
|
|
Maple には、2 つの基本プログラミング構造があります。if 文は、文の式列を条件に従って実行します。for 文は、文の式列の繰り返し実行を制御します。
|
条件分岐 (if文)
|
|
条件に一致する場合にだけ処理を実行するように指定することができます。また、多数の処理のうちの 1 つを、条件に応じて実行することもできます。
if 文を使用して、複数の文のうちの 1 つを、ブール条件 (true、false、FAIL) に従って実行することができます。Maple では、各条件を順番にテストします。ある条件が満たされた場合は、対応する文を実行し、if文から抜けます。
|
構文
|
|
if 文の構文は、以下のとおりです。
条件式 (conditional_expression1, conditional_expression2, ...) には、任意のブール式を指定できます。ブール式は、以下を使用して構築することができます:
•
|
関係演算子 - <、<=、=、>=、>、<>
|
•
|
論理演算子 - and、or、xor、implies、not
|
文の式列 (statement_sequence1、statement_sequence2、...、statement_sequenceN) には、if 文を含む Maple 文の式列を指定できます。
elif 節は、省略可能です。任意の個数の elif 節を指定できます。
else 節は、省略可能です。
|
|
単純な if 文
|
|
最も単純な if 文では、条件式が 1 つだけです。
条件式が true の場合は、文の式列が実行されます。それ以外の場合は、if 文から即座に抜けます。
次に例を示します:
>
|
if not isprime(x) then
ifactor(x);
end if;
|
|
|
else 節
|
|
単純な if 文に else 節が付いている場合は、すべての条件式が false または FAIL を返した場合に、else 節内の文の式列が実行されます。
次に例を示します:
>
|
if false then
"if statement";
else
"else statement";
end if;
|
|
|
elif 節
|
|
if 文に elif 節が付いている場合は、いずれかの条件式が true を返すまで、条件式が順に評価されます。対応する文を実行した後に、if 構造から抜けます。true を返す条件がなかった場合は、if 文から抜けます。
>
|
if not type(x, integer) then
printf("%a is not an integer.", x);
elif x >= 10 then
printf("%a is an integer with more than one digit.", x);
elif x >= 0 then
printf("%a is an integer with one digit.", x);
end if;
|
11 is an integer with more than one digit.
elif 節の順序 : elif 構造の文の式列は、それまでのすべての条件式の評価が false または FAIL を返し、elif 構造の条件式が true を返す場合にだけ実行されます。したがって、elif 節の順序を変更すると、if 文の挙動が変化する場合があります。
次の if 文では、elif 節の順序に誤りがあります。
>
|
if not(type(x, integer)) then
printf("%a is not an integer.", x);
elif x >= 0 then
printf("%a is an integer with one digit.", x);
elif x >= 10 then
printf("%a is an integer with more than one digit.", x);
end if;
|
11 is an integer with one digit.
|
|
elif 節および else 節
|
|
if 文に elif 節および else 節が付いている場合は、いずれかの条件式が true を返すまで、条件式が順に評価されます。対応する文を実行した後に、if 構造から抜けます。true を返す条件がなかった場合は、else 節の文式列が実行されます。
>
|
if not type(x, integer) then
printf("%a is not an integer.", x);
elif x >= 10 then
printf("%a is an integer with more than one digit.", x);
elif x >= 0 then
printf("%a is an integer with one digit.", x);
else
printf("%a is a negative integer.", x);
end if;
|
-12 is a negative integer.
if 文の詳細については、?if で表示されるヘルプページを参照してください。
|
|
|
繰り返し (for 文)
|
|
文の式列を繰り返し実行することができます。文は、以下のいずれかの方法で繰り返し実行することができます。
•
|
カウンター変数の値が制限を超えるまで繰り返す (for/from ループ)
|
•
|
数式のオペランドごとに繰り返す (for/in ループ)
|
•
|
ブール条件が満たされなくなるまで繰り返す (while ループ)
|
|
for/from ループ
|
|
for/from ループ文は、カウンター変数の値が制限を超えるまで、文の式列を繰り返し実行します。
|
構文
|
|
for/from ループの構文は、以下のとおりです。
for/from ループの処理は、以下のとおりです:
1. initial の値を名前 counter に割り当てます。
2. counter の値と final の値を比較します。counter の値が final 値を超えた場合は、ループを終了します (ループ終了テスト)。
3. statement_sequence を実行します。
4. counter の値を指定した値だけ増加します。
5. ループが終了するまで、手順 2 ~ 4 を繰り返します。
from、by、to の各節は省略可能で、for 節と do キーワードの間に任意の順序で記述できます。表 9.1 に、各節のデフォルト値を示します。
表 9.1 : 節のデフォルト値
|
節
|
デフォルト値
|
from initial
|
1
|
by increment
|
1
|
to final
|
無限大 (∞)
|
|
|
|
|
例
|
|
次のループは、1 以上 5 以下の整数の平方根を返します。
>
|
for n to 5 do
evalf(sqrt(n));
end do;
|
カウンター変数 n が 5 を超えると、ループが終了します。
上記のループは、次の for/from 文と同じ結果を返します。
>
|
for n from 1 by 1 to 5 do
evalf(sqrt(n));
end do;
|
by の値には、負の値を指定できます。その場合は、カウンター変数の値が final の値未満になるまでループを繰り返します。
>
|
for n from 10 by -1 to 3 do
if isprime(n) then
print(n);
end if;
end do;
|
|
|
|
for/in ループ
|
|
for/in ループ文は、リストの要素などの数式の各成分 (オペランド) ごとに、文の式列を繰り返します。
|
構文
|
|
for/in ループの構文は、以下のとおりです。
for 節は最初に記述されている必要があります。
for/in ループの処理は、以下のとおりです:
1. expression の最初のオペランドを名前 variable に割り当てます。
2. statement_sequence を実行します。
3. expression の次のオペランドを variable に割り当てます。
4. expression のオペランドごとに手順 2 ~ 3 を繰り返します。すべてのオペランドを処理したら、ループを終了します (ループ終了テスト)。
|
|
例
|
|
次のループは、リスト L に含まれる角 (単位は度) での sin 関数の近似値を浮動小数で返します。
>
|
L := [23.4, 87.2, 43.0, 99.7]:
|
>
|
for i in L do
evalf(sin(i*Pi/180));
end do;
|
|
|
|
while ループ
|
|
while ループは、ブール式が満たされなくなるまで、文の式列を繰り返します。
|
構文
|
|
while ループの構文は、以下のとおりです。
while ループは、ブール式 conditional_expression が false または FAIL になるまで繰り返します。ブール式の詳細については、条件分岐 (if文) を参照してください。
|
|
例
|
|
次のループは、10 進数 872,349 を基数 7 で (下位の桁から上位の桁の順で) 計算します。
>
|
while x > 0 do
irem(x, 7);
x := iquo(x, 7);
end do;
|
このような変換を効率的に実行するには、convert/base コマンドを使用します。
>
|
convert(872349, base, 7);
|
基数が 10 以外の数については、基数が 10 以外の数を参照してください。
|
|
|
一般的なループ文
|
|
while 文は for/from ループや for/in ループ内に記述することができます。
一般的な for/from ループの構文は、以下のとおりです。
一般的な for/in ループの構文は、以下のとおりです。
for ループの反復ごとに、conditional_expression が最初に評価され、ループ終了条件テストが実行されます。
•
|
conditional_expression が false または FAIL の場合は、ループは終了します。
|
•
|
conditional_expression が true の場合は、statement_sequence が実行されます。
|
|
|
無限ループ
|
|
終了条件がないループ (conditional_expression が常に true に評価される while ループなど) を構築することができます。これを無限ループと呼びます。 無限ループは、break、quit、return 文が実行されるまで、またはユーザーが計算を中断無限に実行されます。break、quit、return 文が実行されるまで、またはユーザーが計算を中断するまで
|
|
参考
|
|
for 文およびループの詳細については、?do で表示されるヘルプページを参照してください。
|
|
|
|
9.3 反復コマンド
|
|
Maple には、一般的な選択および繰り返し操作を実行するコマンドがあります。これらのコマンドは、ライブラリコマンドを使用して実装された同様のアルゴリズムよりも効率的です。表 9.2 に、反復コマンドを示します。
表 9.2 : 反復コマンド
|
コマンド
|
説明
|
seq
|
式列を作成します。
|
add
|
数値の和を計算します。
|
mul
|
数値の積を計算します。
|
select
|
条件を満たすオペランドを返します。
|
remove
|
条件を満たさないオペランドを返します。
|
selectremove
|
条件を満たすオペランドと、条件を満たさないオペランドを別々に返します。
|
map
|
数式のオペランドにコマンドを適用します。
|
zip
|
2 つのリストまたはベクトルに 2 項演算を適用します。
|
|
|
|
式列の作成
|
|
seq コマンドは、数式のインデックス値の範囲またはオペランドを使用して、指定した数式を評価し、値の式列を作成します。表 9.3 を参照してください。
表 9.3 : seq コマンド
|
呼び出し手順の構文
|
例
|
seq(expression, name = initial .. final);
|
|
seq(expression, name in expression);
|
>
|
seq(u, u in [Pi/4, Pi^2/2, 1/Pi]);
|
|
|
|
|
|
数式の加算および乗算
|
|
add コマンドおよびmul コマンドは、インデックスで指定した範囲の数式の値、または数式のオペランドの加算または乗算を実行します。表 9.4 を参照してください。
表 9.4 : add および mul コマンド
|
呼び出し手順の構文
|
例
|
add(expression, name = initial .. final);
mul(expression, name = initial .. final);
|
|
add(expression, name in expression);
mul(expression, name in expression);
|
>
|
add(u, u in [Pi/4, Pi/2, Pi]);
|
>
|
mul(u, u in [Pi/4, Pi/2, Pi]);
|
|
|
|
add および mul 呼び出し手順で指定したインデックス範囲の両端 (initial および final) は、評価結果が数値定数になる必要があります。記号総和および記号積については、?sum および ?product
で表示されるヘルプページを参照してください。
|
|
数式のオペランドの選択
|
|
select、remove、selectremove の各コマンドは、ブール値のプロシージャまたはコマンドを、数式のオペランドに適用します。オペランドについては、?op で表示されるヘルプページを参照してください。
•
|
select コマンドは、プロシージャまたはコマンドの結果が true になるオペランドを返します。
|
•
|
remove コマンドは、プロシージャまたはコマンドの結果が false または FAIL になるオペランドを返します。
|
•
|
selectremove コマンドは、入力式と同じ種類の 2 つの数式を返します。
- 最初の数式は、プロシージャまたはコマンドの結果が true になるオペランドで構成されます。
- 2 番目の数式は、プロシージャまたはコマンドの結果が false または FAIL になるオペランドで構成されます。
|
出力の構造は、入力の構造と同一です。 表 9.5 を参照してください。
Maple プロシージャについては、プロシージャを参照してください。
表 9.5 : select コマンド、remove コマンド、selectremove コマンド
|
呼び出し手順の構文
|
例
|
select(proc_cmd, expression);
|
>
|
select(issqr, {198331, 889249, 11751184, 9857934});
|
|
remove(proc_cmd, expression);
|
>
|
remove(var -> degree(var) > 3, 2*x^3*y - y^3*x + z );
|
|
selectremove(proc_cmd, expression);
|
>
|
selectremove(x -> evalb(x > round(x)), [sin(0.), sin(1.), sin(3.)]);
|
|
|
|
選択コマンドの他の引数については、?select で表示されるヘルプページを参照してください。
|
|
集合またはリストにコマンドをマッピングする
|
|
map コマンドは、名前、プロシージャ、コマンドを、集合またはリストの各要素に適用します。表 9.6 を参照してください。
表 9.6 : map コマンド
|
呼び出し手順の構文
|
例
|
map(name_proc_cmd, expression);
|
>
|
map(u -> int(cos(x), x = 0 .. u), [Pi/4, Pi/7, Pi/3.0]);
|
|
|
|
他の数式のオペランドへのマッピング、map コマンドの他の引数、他のマッピングコマンドについては、?map で表示されるヘルプページを参照してください。
|
|
2 つのリストまたはベクトルに 2 項演算をマッピングする
|
|
zip コマンドは、名前または 2 項演算プロシージャ/コマンドを、成分ごとに 2 つのベクトルまたはリストに適用します。
デフォルトでは、返されるオブジェクトの長さは、短い方のリストまたはベクトルの長さになります。値を 4 番目の引数として指定した場合 (省略可能) は、短いリストまたはベクトルで不足している要素の値として使用されます。この場合は、戻り値の長さは、長い方のリストまたはベクトルの長さになります。表 9.7 を参照してください。
表 9.7 : zipコマンド
|
呼び出し手順の構文
|
例
|
zip(proc_cmd, a, b);
zip(proc_cmd, a, b, fill);
|
>
|
zip(f, [i, j], [k, l]);
|
>
|
zip(AiryAi, [1, 2], [0], 1);
|
|
|
|
zipコマンドの詳細については、?zip で表示されるヘルプページを参照してください。
|
|
参考
|
|
ループコマンドの詳細については、該当するコマンドのヘルプページを参照してください。
|
|
|
9.4 プロシージャ
|
|
Maple プロシージャは、Maple 文で構成される簡単なプログラムです。プロシージャを使用して、プロシージャ内に記述した文の式列を実行することができます。
|
単純なプロシージャの定義および実行
|
|
プロシージャを定義するには、文の式列をproc(...) 文および end proc 文で囲みます。通常は、プロシージャ定義を名前に割り当てます。
次のプロシージャは、2 の平方根を返します。
>
|
p := proc() sqrt(2); end proc;
|
注意:Maple では、プロシージャ定義を返します。
読みやすくするため、プロシージャは 複数行に分けて定義し、空白文字を使用して各行をインデントすることをお勧めします。不完全なプロシージャ定義を評価せずに新しい行を開始するには、Shift + Enter とキーを押します。プロシージャの入力が完了したら、Enter キーを押してプロシージャを作成します。
次に例を示します:
>
|
p := proc()
sqrt(2);
end proc:
|
プロシージャ p を実行するには、その名前の後に括弧 (( )) を続けて入力します。
|
|
入力のあるプロシージャ
|
|
入力を指定できるプロシージャを定義することができます。proc 文の括弧で、パラメータ名を指定します。複数のパラメータの場合は、名前をコンマで区切ります。
>
|
geometric_mean := proc(x, y)
sqrt(x*y);
end proc:
|
ユーザーがプロシージャを実行すると、パラメータ名が引数の値に置換されます。
>
|
geometric_mean(13, 17);
|
>
|
geometric_mean(13.5, 17.1);
|
プロシージャの記述、オプション、局所変数、大域変数については、?procedure で表示されるヘルプページを参照してください。
|
|
プロシージャの戻り値
|
|
プロシージャを実行すると、最後の文の計算結果の値だけが返されます。プロシージャ内の各文の出力は返されません。これは、文の区切り文字としてセミコロンとコロンのどちらを使用している場合でも同様です。
>
|
p := proc(a, b)
a + b;
a - b:
end proc:
|
|
|
プロシージャ定義の表示
|
|
単純な Maple オブジェクトとは異なり、プロシージャの名前を入力してその値を表示することはできません。
print (または eval) コマンドを使用してプロシージャ名を評価する必要があります。
|
|
Maple ライブラリのプロシージャ定義の表示
|
|
Maple のプロシージャの定義は、学習ツールとして活用できます。Maple でのプログラム方法を学習するには、Maple ライブラリに含まれているプロシージャの内容を調べることをお勧めします。
デフォルトでは、print コマンドは Maple のプロシージャ内の proc 文と end proc 文、および Maple プロシージャの説明フィールド (ある場合) だけを返します。
Maple ライブラリのプロシージャの定義を表示するには、先にinterface verboseproc オプションの値を 2 に設定します。その後で、print 呼び出し手順を再実行します。
>
|
interface('verboseproc' = 2):
|
|
|
モジュール
|
|
Maple プロシージャは、コマンドの式列を 1 つのコマンドに対応付けます。モジュールは、より複雑なプログラミング構造で、プロシージャおよびデータを対応付けることができます。
モジュールの重要な機能は、変数のエクスポートです。つまり、変数を作成したモジュールの外部でも、その変数を利用できます。ほとんどの Maple パッケージは、モジュールとして実装されています。パッケージのコマンドは、モジュールのエクスポートです。
モジュールの詳細については、?module で表示されるヘルプページを参照してください。
|
|
オブジェクト
|
|
オブジェクトは、モジュールが提供できないデータとプロシージャの関連付けを行います。オブジェクトを使用すると、オブジェクトの 1 つのクラスから複数のインスタンスを作成できます。個別のオブジェクトは独自のデータを持つことができ、さらに他の値やプロシージャをすべてのクラスのオブジェクトと共有できるようになります。オブジェクトの実装済みのクラスは、Maple の組込み型と同じように Maple で使用できます。
オブジェクトの詳細については、?object で表示されるヘルプページを参照してください。
|
|
|
9.5 ドキュメント内でのプログラミング
|
|
Maple コードを書くには、Maple ワークシートを開いて打ち込みを開始すれば良いだけです。しかし、コードを点在させたり、それを非表示にしたりして、読みやすいドキュメントを作成したい場合には、複数の利用可能なオプションがあります。
|
コード編集領域
|
|
コード編集領域を利用すると、閉じた領域内で自然な形のプログラミングを行うことができます。Enter キーを押すとインデントを維持した改行が行われるといった機能が含まれます。図 9.1 に展開したコード編集領域を示します。
新しいコード編集領域をワークシートに挿入するには、以下の手順に従います:
•
|
[挿入(Insert)] メニューから [コードエディタ(Code Edit Region)] を選択します。
|
|
図 9.1 : コード編集領域
|
|
|
この領域内でコードを実行するには、領域内で右クリックし、[コードを実行する(Execute Code)] を選択します。
コード編集領域を最小化することで、コード編集領域内のコードを非表示にすることができます。最小化を行うには、領域内で右クリックし、[コードエディタを折り畳む(Collapse Code Edit Region)]を選択します。領域が最小化されるとアイコンが表示され、その横にコードの一行目の文が表示されます。コードの一行目は、領域内に含まれたプログラムの内容を説明する文にすることをお勧めします。図 9.2 を参照してください。
|
図 9.2 : 折り畳まれたコード編集領域
|
|
|
領域が折り畳まれている状態で領域内のコードを再実行するには、このアイコンをクリックします。
詳細については、?CodeEditRegion で表示されるヘルプページを参照してください。
|
|
スタートアップコード
|
|
スタートアップコードを使用すると、毎回ドキュメントを開く際に、および、再起動を指示した際に実行されるコマンドおよびプロシージャを定義することができます。スタートアップコードは、ドキュメントを読む側からは完全に見えないようになっています。たとえば、ドキュメントコード全体を通じて使用されるプロシージャであるが、表示すると場所をとるとともに、ドキュメントの内容が読みにくくなるようなプロシージャを、この領域を使用して定義することができます。
ドキュメントのスタートアップコードを入力するには、以下の手順に従います:
1. [編集(Edit)] メニューから、[スタートアップコード(Startup Code)] を選択します。あるいは、ツールバーに配置されているスタートアップコードのアイコン
をクリックします。
2. 毎回ワークシートを開く際に、または、再起動を指示した際に実行したいコマンドを入力します。
3. 終了する前に、[文法(Syntax)] をクリックして、入力したコードの構文をチェックします。
4. [保存(Save)] をクリックして内容を保存し、ダイアログを終了します。
|
図 9.3 : スタートアップコードの編集画面
|
|
|
詳細については、?startupcode で表示されるヘルプページを参照してください。
|
|
|
Contents Previous Next Index
|