1.3 属性の宣言と属性値
1.3.4 変数宣言
Maximaで値を割当てた変数は基本的に大域変数になります.この変数は通常は型も属性も何も
ありません.この大域変数に特定の型を設定したり,初期値を割当てる事も出来ます.
先ず,変数に予め型を指定する函数としてmode declare函数とmodedeclare函数があります.但 し,mode declare函数とmodedeclare函数はMaxima内部では同じ函数です.この変数の宣言に加 えて,初期値を設定する函数にdefine variable函数があります.
変数宣言を行う函数
¶ ³
mode declare(⟨変数1⟩,⟨型1⟩,· · ·,⟨変数n⟩,⟨型n⟩,) modedeclare(⟨函数1⟩,⟨型1⟩,· · ·,⟨函数n⟩,⟨型n⟩,) mode identity(⟨引数1⟩,⟨引数2⟩)
define variable (⟨変数名⟩,⟨初期値⟩,⟨型⟩)
µ ´
mode declare函数は⟨変数i⟩に ⟨函数i⟩や⟨型i⟩を設定します.この函数はtranslate函数で変 換する利用者定義の函数で用いる変数の宣言で利用されます.ここでmode declare函数で指定し た型は変数のmode属性に割当てられます.
大域変数のmode属性
¶ ³
型 mode declare函数で利用可能な表記 概要
float float,real,floatp,flonum,floatnum 浮動小数点
fixnum fixp,fixnum,integer 整数
rational rational,rat 有理数
number number,bignum,big 任意精度の数
complex complex 複素数
boolean boolean,bool Boolean
list list,listp リスト
any any,none,any check 任意の型
µ ´
以下に簡単な例を示します.
(%i28) mode_declare(x1,integer);
(%o28) [x1]
(%i29) :lisp (get ’$x1 ’mode)
$FIXNUM
(%i29) mode_declare(x2,rat);
(%o29) [x2]
(%i30) :lisp (get ’$x2 ’mode)
$RATIONAL
(%i30) mode_declare(x2,rational);
(%o30) [x2]
$RATIONAL
この例では変数x1を整数型,x2とx3を有理数型として宣言しています.これらの値は各変数 の mode属性に蓄えられています.この属性は LISPの get函数を用いて取出せます. この様 に,mode declare函数は基本的に型の指定を行う函数です. mode declare函数で指定した変数と型 はmode identity函数を用いて検証が出来ます.
(%i9) mode_identity(integer,x1);
(%o9) 128
(%i10) x1:256.988;
(%o10) 256.988
(%i11) mode_identity(integer,x1);
Warning: x1 was declared mode fixnum, has value: 256.988
(%o11) 256.988
(%i12) mode_identity(float,x1);
(%o12) 256.988
(%i13) :lisp (get ’$x1 ’mode);
$FIXNUM
この様に,mode declareで宣言した型以外の値を与える事は可能で, mode identityも変数に割当 てられた型と異なると文句を言うだけです. mode identityは変数のmode属性と指定された属性 が同じものかどうかを検証するのではなく,単純に変数に割当てられた型がmode identityの引数 で指定された型と同じものかどうかを検証する函数で,正しい場合には変数の値を返し,異なる場 合には警告するだけです.
型の検証に関連する大域変数
¶ ³
大域変数 初期値 概要
mode checkp true 定数変数の型を検証するかどうか制御
mode check errorp false 型エラー処理の制御
mode check warnp true 型エラーの表示の制御
µ ´
大域変数mode checkpがtrueの場合,mode declare函数で宣言する変数に割当てられた値の型 と,新たに宣言する型が矛盾しないか検証し,矛盾する場合はエラーを返します.
(%i17) x0:1.0$
(%i18) mode_declare(x0,integer);
Warning: x0 was declared mode fixnum, has value: 1.0
(%o18) [x0]
(%i19) mode_checkp:false$
(%i20) mode_declare(x0,integer);
(%o20) [x0]
大域変数mode check errorpがtrueであれば,mode declare函数で値が割当てられた変数に対し, 異なる型で変数の宣言を行う場合にエラーを出力します.
大域変数mode check warnpがtrueの場合,mode identity函数は変数に割当てられた値の型と 指定した型が異なる場合に警告を出します.
define variable函数は変数の宣言に加え,初期値と型の設定が行える函数です. 但し,この函数は
属性を上手く使う事で,変数に値を割当てる際に,その変数の利用者が設定した条件に適合するか どうかを検証する事も行える様に出来ます.
このdefine variable函数の処理手順を以下に示しておきます.
• mode declare函数を用いて変数型を宣言します.
• declare函数を用いて変数がspecial属性を持つと宣言します.
• 型がanyでなければ,属性assignに属性値assign-mode-checkを設定します. この属性値が 設定されていない変数に対して,Maximaは変数への値の割当の際に,値の検証を行いません.
値の検証を行う為には大域変数のvalue check属性に述語函数を割当てておく必要がありま す.この設定ではqput函数が有効です.
• 変数に値が割当てられていなければ,指定した初期値を設定します. もしも値が既に割当てら れていれば,define variable函数は与えられた初期値を割当てずに,そのままの値にしておき ます.
割当ての際に,変数値の検証を行う方法は,qput函数を用いて宣言した大域変数のvalue check属 性に変数値を検証する述語函数名を割当ておきます.以下に,動作例を示しておきましょう.
(%i1) ptest(y):=if not primep(y) then error(y,"is not prime!!")$
(%i2) define_variable(tama,5,integer)$
(%i3) qput(tama,ptest,value_check)$
(%i4) tama;
(%o4) 5
(%i5) tama:15;
15 is not prime!!
#0: ptest(y=15)
-- an error. Quitting. To debug this try debugmode(true);
(%i6) :lisp (get ’$tama ’assign) ASSIGN-MODE-CHECK
(%i6) define_variable(mike,5,any)$
(%i7) properties(mike);
(%o7) [value, special]
(%i9) properties(mike);
(%o9) [value, [user properties, value_check], special]
(%i10) mike:15;
(%o10) 15
(%i10) :lisp (get ’$mike ’assign) NIL
(%i10) :lisp (put ’$mike ’assign-mode-check ’assign) ASSIGN-MODE-CHECK
(%i10) mike:15;
15 is not prime!!
#0: ptest(y=15)
-- an error. Quitting. To debug this try debugmode(true);
この例では,最初に素数でなければエラーを返す述語函数ptestを定義し,それから, define variable 函数で大域変数tamaに初期値5を与えて整数変数として宣言します.それから,qput函数を用い てcheck value属性にptestを与えます.この時, 変数mikeに15を設定しようとすれば,15は素数 ではないのでエラーになっています.
ここまでの動作をもう少し詳しく解説しましょう.先ず,define variable函数による宣言で,変数 の型をintegerと宣言しています.define variable函数は, 変数の型をany以外に指定していれば, 宣言する大域変数のassign属性に内部函数のassign-mode-check函数を割当てます.この内部函数
は変数のvalue check属性に設定された函数を用いて変数の評価を実行する函数です.次に,この
value check属性の設定でqput函数を用いています.ここでの例では,大域変数tamaのvalue check
属性にptest函数を割当てていますね.すると,大域変数tama
に値を割当てる時に,assign-mode-check函数が,大域変数tamaのcheck value属性に割当てられた述語函数で割当てようとする値を
評価します.この例では,ptest函数に15が引渡されます.この例では15が素数でない為にfalseと なり,変数に15が割当てられません.
次の例では, 大域変数mikeの型を any とした場合です. この場合,変数 mikeの value check 属性に値を設定しても,先程の様にmike:15を実行した場合にエラーも何も出ません.この場合, 大域変数mikeのassign属性にassign-mode-checkが設定されていない為です.これはLISPで
(get ’$mike ’assign) を実行すれば, NILが返されるので判ります.
そこで, :lisp (put ’$mike ’assign-mode-check ’assign) として見ましょう.これによって,属性 as-signの値としてassign-mode-checkを設定されます.すると,割当の際に検証が実行される様になり ます.