• 検索結果がありません。

函数定義に関連する函数

ドキュメント内 , (ページ 138-146)

第 9 章 多項式について

12.5 函数定義に関連する函数

132 第12章 函数定義 block

block ([h局所変数1i,· · ·,h局所変数ki],h1i,· · ·,hji)

MAXIMAのblockはFORTRANのsubroutine,PASCALのprocedureに似たものです. block 文は文の集合体ですが,block内部の文にラベル付けが行え,局所変数も扱えます.尚,局所変数を用 いない場合には,局所変数のリストを省略しても構いません.局所変数はblock文外部にある同名の (大域)変数との名前の衝突を避ける為に用いるものです.同名の(大域)変数が存在した場合, block 文の実行中,その変数はスタックに保存されるので,その間は参照出来ません.block文が終了した時 点で,スタックに保存さていた値はもとに戻され, block文の局所変数の値は失なわれてしまいます.

尚,block内部で用いられているものの,block文の局所変数リストに含まれていない変数はblock 文の外部で用いられている変数と同様に大域変数として扱われます.その為,値はblock文の終了後 も保持されます.

blockの値は,最後の文の値かblockからreturnに渡された引数の値となります. 函数goは制御

をgoの引数でラベル付けされたblock内の文に移動する為に使います. 尚,文のラベル付けは,block でアトムを文の前に置く事で対処します. 例えば,block([x],x:1,loop,x:x+1,· · ·,go(loop))の様にし ます. goの引数はblock内部に現われるラベル名でなければなりません.goを含まないblock文中 のラベルにgoで移動する事は出来ない.blockは通常,函数定義の右側に現われるが,他の場所に置 く事も同様に可能です.

break

break (h引数i,· · ·) h引数iの評価と表示を行い,(maxima-break)にて利用者がその環境を調 べ,変更する事が出来る様にします.(maxma-break)からはexit;を入力すれば計算が再開されます.

尚,Cntrol-a(ˆa)でmaxima-breakに何時もで対話的に入る事が出来ます.Cntrl-xはmaxima-break 内部で,本体側の処理を終了せずに,局所的に計算を止める事に用いても構いません.

buildq

マクロの定義で用います.

catch

catch (h1i,· · ·,hni)

throwと対で用います.

この非局所的回帰(non-local return)は,最も近い throwに対応するcatchに行きます. その 為,throwに対応するcatchが必ず必要で,そうでなければエラーになります.ここで,hiiの評価

が何らのthrowの評価に至らなかった場合,catchの値は最後の引数hniの値となります.

(c1) g(l):=catch(map(lambda([x],

if x<0 then throw(x) else f(x)),l));

(c2) g([1,2,3,7]);

(d2) [f(1), f(2), f(3), f(7)]

(c3) g([1,2,-3,7]);

(d3) - 3

函数gは,lが非負の数のみであればlの各要素に対するfのリストを返します. それ以外では,g はlの最初の負の要素を捉え(catch)て,それを放擲(throw)します.

compfile

compfile (hファイルi,h函数1i,· · ·,h函数ni)

MAXIMAの指定した函数のh函数1i,· · ·,h函数niをLISPの函数に変換し,hファイルiに書込 みます.

(%i28) neko(x):=sin(x);

(%o28) neko(x) := sin(x)

(%i29) compfile("mike",neko);

Translating neko

(%o29) /home/yokota/mike

(PROGN (DEFPROP $NEKO T TRANSLATED) (ADD2LNC ’$NEKO $PROPS)

(DEFMTRFUN ($NEKO $ANY MDEFINE NIL NIL) ($X) (DECLARE (SPECIAL $X)) (SIMPLIFY (LIST ’(%SIN) $X))))

compile

compile (h函数1i,· · ·,h函数ni) compile (functions) compile (all)

指定したMAXIMAの処理言語で記述した函数をLISPの函数に変換し, それをLISPの函数

COMPILEを用いてコンパイルします. 尚,compile函数は函数名リストを返します.

引数にfunctionsやallを指定すると利用者定義函数を全てコンパイルします.

尚,大域変数functionsには利用者定義函数の名前がリストの成分として保持されています.

define

define (h函数i(h引数1i,· · ·,h引数ni),h本体i)

函数を定義します.この函数は引数としてh引数1i,· · ·,h引数niを持ち,函数内部の文はh本体i に記述します. この函数定義はh函数i(h引数1i,· · ·):= ”h本体iと同値です.

define variable

define variable (h変数名i,hデフォルト値i,hi,hオプションの文書i)

MAXIMA環境に大域変数を導入する函数です.主にパッケージで利用する環境変数の設定等で

用いられます.

hデフォルト値iは定義した大域変数の初期値となりますが,この値は次のhiに適合するもの でなければなりません.

hiにはboolean,fixnum(16ビット整数),number(多倍長整数), rational(有理数)とfloat(浮動 小数点),或いは,これらの内のいずれかを意味するanyを設定します.

134 第12章 函数定義 hオプションの文書iは省略可能な引数で,文字列を設定します. これは,translate fileが文書文 字列を含むパッケージに用いられた時,マニュアル,用例ファイル,例えば,describe向けに適した書 式の文書文字列を含むlispのファイル出力となります.

any以外のモードでdefine variableとされた任意の変数でvalue check属性を与える事が可能で す.この属性は,利用者がその変数に設定しようとする値に関して呼出された1引数の函数となり ます.

ここで,単純な例でdefine variableの動作を説明しましょう.先ず, define variable(foo,true,boolean);

と入力すると,以下の処理が逐次実行されます.

1. mode declare(foo,boolean)を実行し,変数fooがBooleanである事を宣言します.

2. 変数fooに変数に値が束縛されていなければ, foo:trueを実行し, 変数fooにtrueを割当て ます.

3. declare(foo,special)を実行し,変数fooがspecialであると宣言します.

4. 間違った変数型の値を設定する事が決してない様に,属性を割当てます. ここでは,fooを

booleanとして定義しているので, foo:44を実行すると,その結果はエラーになります.

dispfun

dispfun (h函数名1i,· · ·,h函数名ni) dispfun(all)

利用者定義の函数であるh函数名1i,· · ·,h函数名ni)を表示します. この函数の表示では,函数を 定義した時点での函数や定数等をそのまま表示します.

引数にallを設定すると,大域変数functionsとarraysで与えられる函数を全て表示します.

fundef

fundef(h関数名i)

h関数名i)に対応する函数の定義を返します. fundefはdispfunに似ていますが,fundefでは

display函数を呼出さない点で異なります.

(%i9) neko(x):=sin(x)*exp(x);

(%o9) neko(x) := sin(x) exp(x)

(%i10) dispfun(neko);

(%t10) neko(x) := sin(x) exp(x)

(%o10) done

(%i11) fundef(neko);

(%o11) neko(x) := sin(x) exp(x)

この例で示す様に,dispfunを実行すると結果は%tラベルに表示されていますが,fundefの方は通 常の%oラベルに表示されています.

funmake

funmake (h関数i,[h引数1i,· · ·,h引数ni])

h関数iで指定した函数を呼出して評価を行う事はしません. 単純に,h関数>(<引数1i,· · ·,h引 数ni)を返すだけです.

(%i2) funmake(f,[x,y,z]);

(%o2) f(x, y, z)

(%i3) funmake(neko,[x,y,z]);

(%o3) neko(x, y, z)

(%i4) funmake(expand,[128,"うちのタマ知りませんか?"]);

(%o4) expand(128, うちのタマ知りませんか?)

(%i5) funmake(a,[1,2,3]);

(%o5) a(1, 2, 3)

(%i6) a:10;

(%o6) 10

(%i7) funmake(a,[1,2,3]);

Bad first argument to ‘funmake’: 10

-- an error. Quitting. To debug this try debugmode(true);

(%i8) funmake(’a,[1,2,3]);

(%o8) a(1, 2, 3)

関数に指定したアトムに値が束縛されている場合,そのアトムは内部で評価される為,エラーに なります.この場合は,単引用符’を先頭に付けて名詞型とすれば問題ありません.

local

local (h局所変数1i,· · ·,h局所変数ni)

この函数の函数が利用される文中で,h局所変数1i,· · ·,h局所変数ni を全ての属性に対して局所 的なものにします.localはblock文,函数定義の本体,lambda式,又はev函数でのみ一度だけ使え

ます.このlocal函数は文脈からも独立しています.

mode declare

mode declare(h変数1i,h変数型1i,· · ·,h変数ni,h変数型ni)

modedeclareと同義です.このmode declareはtranslate函数やcompile函数でLISP函数に変 換したりコンパイルする利用者定義の函数内部で局所変数の宣言の後で,これらの変数型宣言で用 います.

引数はh変数iiとその変数に対応するh変数型iiの組で, 変数型はboolean,fixnum(機械長整 数),number(整数),rational(有理数)やfloat(浮動小数点),或いは,これらの何れからの値が取れる anyの何れか一つを指定します.

又,h変数iiが配列で,参照される配列の全ての要素が値を持っているとすると,配列の範囲を最初に 宣言する場合は, array(hyii,h次元1i,h次元2i,· · ·)ではなく, array(hyii, complete,h次元1i,h次元2i,· · ·)

136 第12章 函数定義 を用いる必要があります.

ここで,配列の全ての要素がfixnum(float)の場合,completeの代りにfixnum(float)を用います.配 列の全ての要素が同じ型の数値の場合,例えばmであれば, mode declare(completearray(yi),m)) を効率的な変換の為に使わなければなりません.更に,配列を用いた数値は予想される配列の大き さを宣言する事でより速く動作させる事が可能です.

mode declare(completearray(a[10,10]),float)は,10x10の浮動小数点の配列向けです.加えて,函 数結果をfunction(f1,f2,...)を引数として宣言しても構いません.尚,f1,f2,...は函数名です.

mode declare([function(f1,f2,...),x], fixnum,q,completearray(q),float)で,xとf1,f2,...によって 返される値が機械長の整数である事と,qが浮動点小数配列である事を宣言しています.

mode identity

mode identity (h引数1i,h引数2i)

mode declareと用いられる特殊な形式で,宣言すべきマクロ, 例えば,flonum型のリストのリス

トや,他のデータの混合物になります.

h引数1iはプリミティブの値の型名で, mode declareに与えられるものです.即ち,[float,fixnum,number,list,any]

の何れかになります.h引数2iは式で,評価されて,mode identityの値として返されます.しかし,返 された値がh引数1iで宣言されたモードに合致しないものであれば,エラーや警告が出力されます.

重要な事は,maximaからlispへの変換で決められた式の型がh引数1iとして与えられ,h引数2i に続く全てのものから独立している事です. その為, x:3.3; mode identity(fixnum,x);と入力する と,警告が出て,mode identity(flonum,x)は3.3を返します.

これは色々な使い方があり,例えば,first(l)が数(number)を返す事が判っていれば,mode identity(number,first(l)) と書いても良いでしょう. しかし,より効率的な方法は,新しいプリミティブ,

firstnumb(x)::=buildq([x],mode\_{}identity(number,x));

を定義して,数のリストの最初の元を取る時は何時もfirstnumbを用いる事です.

translate

translate (h函数1i,· · ·,h函数ni) translate (functions) translate (all)

translateはMAXIMAの処理言語で記述した利用者定義の函数をLISPの函数に変換する函数

です.MAXIMA言語で記述された函数は,裏のLISPで解釈されて,実行されます.これをLISPの 函数にすれば,解釈する手間は省ける分,処理の高速化が望めます.

引数は,h函数1i,· · ·,h函数niの様に利用者定義函数を直接指定する方法,に加えて,引数にallや

functionsを指定して,利用者定義函数を一度に変換する事も出来ます.尚,大域変数functionsは利

用者定義函数の名前が全て登録されるリストです,

変換される函数には,内部で局所変数を利用する場合には特に,mode declareで局所変数の型を 宣言する必要があります.これは,より効率的なLISP函数を生成する為には必要な事です.

例えば,block文を用いた函数を定義する場合,局所変数を宣言した直後に, mode declareを入れ て,局所変数の型を宣言します.

f(x1,x2,...):=block([局所変数1,局所変数2,...],

mode_declare(局所変数1,型1,局所変数2,型2,...),\langle 函数本体>)

尚,函数をtranslateで変換すると,大域変数savedefがfalseの場合,変換された函数の名前は大

域変数functionsに割当てられた函数名リストから削除されて,今度は大域変数propsに割当てら

れたリストに名前が追加されます.

当然の事ですが,函数は虫取りが完遂されるまで変換すべきではありません. 更に,translate函数 は,変換する函数内部の式はきちんと簡易化されていると仮定しています.そうでなければ,最適化 されていないLISP函数が生成され,変換する意味が半減するかもしれません.

その為,大域変数のsimpをfalseに設定して変換されるべき式の簡易化を禁じる事をしてはいけ ません.

注意すべき事に,translate函数を用いてLISPの函数に変換しても,MAXIMAとLISPの整合性 の問題から,以前と同じ動作をする保証はありません.

translate file

translate file (hファイルi) translate file (hファイルi,hLISPファイルi)

MAXIMA言語で記述したプログラムを含むファイルをLISP

函数のファイルに変換します.trans-late fileはMAXIMAのファイル名,LISPのファイル名とtranslate fileが評価した引数の情報を含 むファイル名を成分とするリストを返します.

最初の引数はmaximaファイルの名前で,オプションの第二の引数は生成すべきLISPファイル 名です.第二の引数は第一引数に,trispのデフォルト値のtr output fileの値を第二ファイル名のデ フォルト値として与えます. 例えば, translate file(”test.mc”)) でファイルtest.mcをLISPファイ ルのtest.lispに変換します.

更に,生成されるものには変換器が出力した様々な重要性の度合を持った警告メッセージのファ イルがある.第二ファイル名は常にunlispです. このファイルは変数を含み,それには変換された コードでのバグ追跡の為の情報が含まれています. 変換に関連する大域変数は多く,名前も長いも のが多い為, apropos(tr )を実行すると,trで開始するMAXIMAの大域変数等のリストが出力さ れるので,このリストを出して名前を確認するのも良いでしょう.

translate file(”foo.mc”), loadfile(”foo.lisp”)はbatch(”foo.mc”)にある制限(例えば,”や

tr warnings get tr warnings get ()

変換中に変換器が出力する警告のリストを表示します.

compile file

compile file (hファイルi)

compile file (hファイルi,hコンパイルされたファイルi)

compile file (hファイルi,hコンパイルされたファイルi,hLISPのファイル名i)

指定されたhファイルiにはMAXIMAのプログラムが含まれており,これをLISP函数に変換 し,その結果をcompile函数でコンパイルします. 変換とコンパイルに成功すると,今度は結果を

MAXIMAに読込みます.

compile fileは四個のファイル名のリストを返します.このリストに含まれるファイル名は,元の

MAXIMAプログラムファイル, LISPへの変換ファイル,変換に関する註釈ファイルとcompileで

ドキュメント内 , (ページ 138-146)