例28を実行すると,6,8,10のような無意味なピタゴラス数も出力します。ENDとすればいいでしょう。このようなプログラムを作るのは,実際には容易ではありません。例28のプログラムが変数名としてx,y,zでなくa,b,cを用いていたとしたら,合体させたプログラムは正常に動作しません。外部関数定義BASICには多くの関数が組込み関数として用意されていますが,それで十分とはいえません。DEF文は利用者が関数を定義する機能を提供していますが,DEF文では数値式で書けるような関数しか定義できません。BASICには,より複雑な処理をしなければ求められないような関数でも定義できる機能が用意されています。前項に示したプログラムは,2数a,bの最大公約数をGCD(a,b)と書くことにすればもっとわかりやすく書くことができます。そのために外部関数定義というものを使います。BASICのプログラムではEND行までの部分を主プログラムといいます。END行以降には外部手続きと呼ばれるものが続きます。外部関数定義も外部手続きの一種です。例47は,200行から280行までの部分がGCD関数を定義する外部関数定義です。FUNCTION行で終わります。FUNCTION行には,関数名と引数(ひきすう)を書きます。引数は括弧でくくって書きます。引数が2個以上ある場合にはそれらをコンマで区切って書きます。FUNCTION主プログラムと外部手続きはプログラム単位と呼ばれます。外部関数を利用するプログラム単位には,その外部関数の名前を関数名として用いることの宣言文を書きます。上のプログラムでは,主プログラムで外部関数としてGCDを用いるために100行のような宣言文を書いています。このような宣言を書くことで,外部関数の名前と同じ組込み関数があったとしても正しく動作させることが可能となります。宣言文は,実際に関数を使う行よりも上の行に書きます。続けて目的の関数名を書くだけです。[Note](仮称)十進BASICの現バージョンでは組込み関数名と一致しない外部関数を用いる場合には宣言文を省略できますが,将来のバージョンでは組込み関数を増やすかも知れないので,宣言文は必ず書いてください。将来のバージョンでは外部関数宣言の省略を許さないように文法を変更することも検討しています。上のプログラムでは,GCD関数を130行で利用しています。これを関数の呼び出しといいます。関数を呼び出すとき書く引数(上のプログラムではxとy)を実引数と呼びます。GCD関数が呼び出されると,変数a,bに実引数の値が代入されて,関数定義部の各行が順に実行されます。関数の値は,270行にあるような関数名に代入する形のLET文で決定されます。プログラム単位は,変数名に関して独立した存在です。異なるプログラム単位に同じ名前の変数があってもコンピュータの内部では別の変数です。例47の主プログラムの変数x,y,zをa,b,cに書き換えたとしても,プログラムは正常に動作します。利用すれば3数の最大公約数を求めるのは簡単です。次のようにすればいいのです。7!は6!に7をかければ求められます。6!は5!に6をかければ求められます。いう式に行き着いて問題が解決します。このように,同種の,しかし,より規模の小さい問題に帰着させることを繰り返し実行して問題を解決する手法を再帰と呼びます。BASICでは,関数を定義するときに自分自身を利用することができます。次のプログラムでは,階乗(factorial)を計算する関数FACTの定義のなかで自分自身を利用しています。コンピュータのプログラミングでは,関数の定義のなかで自分自身を呼び出すことを再帰呼び出しといいます。FUNCTIONBASICで関数の再帰呼び出しがうまく機能するのは,関数が呼び出されるごとに変数が新たに割り当てられるからです。FACT=FACT(n-1)*nとしても正しく動作しますが,FACT(n-1)の計算の途中でnの値が変化してしまうと正しく動作しないはずです。関数FACTが呼び出されるごとに,別の場所にその回の呼び出しにだけ通用する変数nが新たに割り当てられているのです。最大公約数を求めるユークリッドの互除法も再帰的な算法の典型例です。BASICではこの算法を次のように書くことができます。BASICには円を描く命令は用意されていませんが,円を描く命令を定義して利用する手段が用意されています。それを絵定義と呼びます。PICTURE100行から150行までの部分を外部絵定義といいます。PICTUREに続けて絵名を書きます。上のプログラムでは,circleが絵名です。必要があれば外部関数定義の場合と同様に引数部を書くこともできます。絵circleは原点を中心とする半径1の円を描きます。正確にいえば正360角形を描いているだけですが,コンピュータのディスプレーでは円に見えると思います。プログラム単位はOPTION文に関しても独立です。DEGREESを主プログラムに書いても外部絵定義では角の大きさの単位は変更されません。絵を実行するのにDRAW文を用います。DRAW文では絵を描くときに原点を中心とする拡大・縮小や回転,あるいは平行移動などの変形を指定することができます。SCALE(a,b)は原点を中心とするx軸方向にa倍,y軸方向にb倍の拡大です。a,bは負の数でも差し支えありません。a=bの場合には,SCALE(a)のように書くこともできます。SHIFT(a,b)は,x軸方向にa,y軸方向にbの平行移動です。ROTATE(α)は,原点を中心とする角αの回転です。変形は*で結合することで合成することもできます。合成した変形は左から順に実行されます。SCALE(3,2)*SHIFT(3,4)は拡大してから平行移動します。外部副プログラム外部副プログラムの機能はほとんど外部絵定義のなかに含まれています。文法的にも用いる用語が異なるだけでほとんど同じです。副プログラムでは図形を変形して描くことはできません。例51では,点(a,b)を中心とする半径rの円を描く副プログラムcircle(a,b,r)を定義しています。副プログラムを呼び出すのにCALL文を用います。副プログラムに引数があるときは関数と同様の形式で引数を記述します。絵および副プログラムには関数定義と異なる特性があります。それがこれから説明する変数引数です。SUB例52で副プログラムdoubleは実引数として書いた変数の値を2倍にして返します。副プログラムでは,実引数に変数を書くと,副プログラムの実行中,実引数の変数に割り当てられた領域を引数の領域として使います。したがって,副プログラムの実行中に引数の値を変更すると,実引数の値が変化します。double(2*a)とした場合には,副プログラムに2*aの計算結果の数値が引き渡されるだけです。整数解を探すという問題を考えてみます。この型の方程式は1つ解を持てば無数の解を持つことになるので,ここでは解をひとつ求めればよいものとします。b=0のときの解は明らかです。yの値は何でもよいのですが,たとえば,y=0とでもしておけばよいでしょう。反対にcがaで割り切れなければ解はありません。b≠0のときは,aをbで割ったときの商をq,余りをrとします。a=bq+rですから,はじめの方程式をb(qx+y)+rx=cと書き換えることができます。したがって,方程式bu+rv=cの解が求まれば,x=v,y=u-qvが求める解ですし,bu+rv=cに解がなければ解はありません。ここで,bu+rv=cの解は必ず確定します。いうと,ax+by=cとbx+ry=cを比較したとき,yの係数は確実に0に近づいているからです。yの係数は整数ですから,何回かの繰り返しの後,必ず0になります。EXCEPTION文は指定した例外番号(EXTYPE)の実行時エラー(例外)を起こします。1〜999の例外番号は利用者用として予約されています。EXECPTION構文で囲まれていなければ,例外は呼び出し元に伝達されます。