ユーザー定義の式中関数¶
「式中で使える関数」として、組み込み関数だけでなく@~~
で定義した関数を式中で呼び出すことも可能です。
「式中で使える関数」のうち組み込み関数については式中で使える関数を参照してください。
書式¶
呼び出される関数は#FUNCTION
フラグまたは#FUNCTIONS
フラグを持ち、RETURNF
で終わる必要があります。
#FUNCTION
を付けると数値を返す関数と認識されます。
#FUNCTIONS
を付けると文字列を返す関数と認識されます。
#FUNCTION(S)
を付けた関数は通常のRETURN
で終了することはできません。代わりにRETURNF
で終了します。
RETURNF
には数式または文字列式を指定します。これは#FUNCTION(S)
で示した型と一致している必要があります。
RETURNF
の引数を省略した場合、またはRETURNF
無しで関数の終端に到達した場合は0
または空文字列を返します。
X = GET_CFLAG(TARGET, Y)
STR = %GET_NAME(TARGET)%
@GET_CFLAG(ARG:0, ARG:1)
#FUNCTION
SIF ARG:0 <= 0 || ARG:0 >= CHARANUM
RETURNF 0
RETURNF CFLAG:(ARG:0):(ARG:1)
@GET_NAME(ARG:0)
#FUNCTIONS
SIF ARG:0 <= 0 || ARG:0 >= CHARANUM
RETURNF ""
RETURNF NAME:(ARG:0)
※関数定義の引数を()
でくくっていますが、これは定義の場合は必須な文法ではありません。
式中関数を呼び出す場合は()
でくくった文法を用いる必要があります。
通常の関数と同様に関数名と引数をカンマでわけることもできます。
以下の2行は同じ意味です。
@GET_CFLAG(ARG:0, ARG:1)
@GET_CFLAG, ARG, ARG:1
また、引数に初期値を設定することができます。
初期値についての文法は自作関数における引数指定をご覧ください。
制限¶
CALLから呼び出せない¶
FUNCTION(S)
フラグを付けた関数はCALL
など通常の呼び出しはできません。
式中でのみ呼び出せます。
;エラー
CALL GET_CFLAG, X, Y
@GET_CFLAG(ARG:0, ARG:1)
#FUNCTION
SIF ARG:0 <= 0 || ARG:0 >= CHARANUM
RETURNF 0
RETURNF CFLAG:(ARG:0):(ARG:1)
#FUNCTION(S)
を呼び出すための専用命令CALLF
、CALLFORMF
からであれば呼び出せます。
一部の命令は使用不可¶
FUNCTION(S)
フラグを付けた関数の中ではWAIT
など入力を伴う命令、CALL
など関数呼び出しを伴う命令は使用できません。
使用するとエラーになります。
CALL
命令は使用できませんが、FUNCTION(S)
フラグを持つ関数を式中で呼び出すことはできます。
また、CALLF
、CALLFORMF
命令による#FUNCTION(S)
の呼び出しは可能です。
オーバーロード不可¶
複数の#FUNCTION(S)
関数を引数の数、型の違いによって呼び分けることはできません。
同じ名前の関数は1つしか定義できず、同名関数を複数定義した場合には最初に定義された関数のみが有効です。
組み込み関数の上書き¶
組み込み関数と同名の関数を定義した場合、その組み込み関数は呼び出せなくなります。
例えば、@ABS
を定義すると元のABSを呼び出すことはできなくなります。
組み込み関数が上書きされているとき、Emueraは起動時に警告を表示します。
組み込み関数が上書きされていると意図した動作をしないことがあるため、コンフィグによって関数の上書きを禁止することができます。
意図的に上書きする場合のため(推奨しません)、上書きされても警告しないようにするコンフィグオプションもあります。
注意事項¶
FUNCTION(S)
フラグを付けた関数の中でローカル変数以外の変数を変化させるべきではありません。
ローカル変数以外の変数を変化させる関数(副作用のある関数)は後述する短絡評価や式の評価順序などにより動作が変わるおそれがあります。
また、デバッグコマンドやデバッグ用の変数ウォッチウインドウからなどの予期しない呼び出しにより意図しない動作をするおそれがあります。
短絡評価による呼び出し省略¶
式中に関数があっても短絡評価によって呼び出されないことがあります。
例えば以下のスクリプトは、IF
文の中でGET_ASSI_CFLAG
を呼んでおり、GET_ASSI_CFLAG
の中でASSI
を変更しています。
IF X || GET_ASSI_CFLAG(0)
Y = CFLAG:ASSI:2
ENDIF
@GET_ASSI_CFLAG(ARG:0)
#FUNCTION
SIF ASSI < 0
ASSI = 0
RETURNF CFLAG:ASSI:(ARG:0)
一見するとY = CFLAG:ASSI:2
の実行時にASSI < 0
になることはないように見えます。
しかし、X
が0
でない場合は短絡評価によりGET_ASSI_CFLAG
が実行されないため、ASSI < 0
のままCFLAG:ASSI:2
を評価しようとしてエラーになる場合があります。
式の評価順により結果が変わる¶
式中での変数・関数の評価順は不定です。
副作用のある関数は式の中の関数がどの順番で呼び出されるかに依存する場合があります。
そのようなコードを書かないでください。
呼び出し順はEmueraのバージョンが同じであれば同じになるでしょうが、将来変更されるかもしれません。
下のスクリプトでは、@ADDCHARA_CFLAG
中でTARGET
を変更しています。
X = CFLAG:TARGET:10 + ADDCHARA_CFLAG(0)
@ADDCHARA_CFLAG(ARG)
#FUNCTION
ADDCHARA ARG
TARGET = CHARANUM -1
RETURNF CFLAG:TARGET:2
@ADDCHARA_CFLAG
より前にCFLAG:TARGET:10
を評価するか、後でCFLAG:TARGET:10
を評価するかによってCFLAG:TARGET:10
の指す変数が変わってきます。
したがってこのスクリプトは評価順に依存します。
#FUNCTION(S)
フラグを付けた関数の中でADDCHARA
やTARGET
への代入をすべきではありません。
デバッグ用の機能により呼び出されることがある
#FUNCTION(S)
フラグを付けた関数は*.ERB
ファイル中のスクリプトからだけではなく、デバッグコマンドやデバッグ用の変数ウォッチウインドウから動的に呼び出されることがあります。
特に変数ウォッチは頻繁に値を更新しようとし、更新のたびにその関数を呼び出します。
副作用を持つ関数はこのような呼び出しにより誤動作を起こす可能性があります。