====== 関数の定義・呼び出し ====== [[erabasicリファレンス|リファレンストップ]] · [[erabasicリファレンス_総索引|名前の総索引]] 関数の定義、引数・戻り値、呼び出し、ユーザー定義式中関数を調べます。 ===== 自作関数における引数指定 ===== ※1.54uまでと1.60以降で仕様が異なります!※\\ ==== 書式 ==== 関数側    @(関数名),(引数1),{(引数2)....}    引数は数値ならARG(:0,1,2...)、文字列ならARGS(:0,1,2...)    関数中で#DIM、#DIMSを用いて定義したプライベート変数も引数に指定可能 呼び出し側    CALL (関数名),(引数1),{(引数2)....} 数値は数式または文字列式が使用できます。\\ 文字列リテラル(定数)を引数にするときは""でくくってください。\\ 書式付の文字列リテラルを引数にするときは@"〜〜"で書いてください。\\ CALL以外にJUMP、CALLFORM、TRYCALLなどでも同じ書式が使えます。\\ 関数側の引数はいくつでも指定できます。\\ ver1.808現在、関数側と呼び出し側で型が異なる場合、数値から文字列、文字列から数値に関わらず変換せずエラーになります。\\ ver1.807以前と同様に文字列型の引数に数値を与えて呼び出したい場合、コンフィグ設定を変更するか、TOSTR関数を用いてください。\\ 引数は省略できます。省略した場合、数値型の場合は0、文字列型の場合は空文字列が代入されます(初期値を設定していない場合)。\\ 呼び出された関数側ではARGとARGSで渡された値を参照できます\\ 基本的に値渡しなのでARGの中身を変更しても渡した元の変数等の値は変化しないことに注意してください。\\ ARGやARGS、または関数中で#DIM、#DIMSを用いて定義したプライベート変数以外の変数(AやSTR)を引数にすることも可能ですが、いくつか制限があります。\\ ver1.808現在、これらの変数を用いた場合は初期値を設定できず、また引数を省略できません。\\ ;定義 @FOOBAR, ARG:0, ARGS:0 〜〜 @HOGEHOGE, ARG:0, ARG:1, ARG:2 〜〜 ;呼び出し ;変数で指定 CALL FOOBAR, X , STR:0 ;定数で指定 CALL FOOBAR, 123 , "あいう" ;書式付文字列で指定 CALL FOOBAR, 123 , @"[{COUNT}] あいう" ;式で指定 CALL FOOBAR, X + 10, "あいう" * 10 ;引数の省略-全部 CALL FOOBAR ;引数の省略-第1引数 CALL FOOBAR, , "あいう" ;引数の省略-第2引数 CALL FOOBAR, 123 <エラーになる例> ;エラー(引数が多すぎる) CALL FOOBAR, X , STR:0, Y ;エラー(引数の型が違う-数値型の第1引数に文字列を代入しようとしている) CALL FOOBAR, "あいう", "かきく" ;エラー(引数の型が違う-文字列型の第2引数に数値を代入しようとしている) CALL FOOBAR, 123 , 456 <動作はするが推奨されない例> ;代入先はARG、ARGSでなくても可能ですが、通常はARGを使うことを推奨します @FOOBAR, X, Y ;代入先を可変にすることも可能ですが可読性が下がります。 @FOOBAR, ARG:X, ARG:Y ;可読性が下がります。 @FOOBAR, ARG:0, ARG:(ARG:0) ==== 引数の初期値 ==== 関数の引数に初期値を設定することができます。\\ 初期値を設定する場合、関数側は以下のようになります。\\    @(関数名),(引数1 = 初期値1),{(引数2 = 初期値2)....}    引数は数値ならARG(:0,1,2...)、文字列ならARGS(:0,1,2...)、    または関数中で#DIM、#DIMSを用いて定義したプライベート変数    それ以外を指定した場合初期値は設定できません。 指定可能な初期値は定数および定文字列のみで、変数は指定できません。\\ また文字列の初期値は""でくくってください。\\ 初期値を設定し、呼び出し側が引数を省略した場合、初期値に設定した値が代入されます。\\ 省略せずに関数を呼び出した場合は、通常通りARGとARGSに渡された値が代入されます。\\ ;初期値設定(部分省略もできます) @FUNCTION, ARGS:0 = "かきく", ARG:0 = 111, ARG:1, ARG:2 = 200 〜〜 ;エラー(初期値は定数および定文字列のみ) @FOOBAR, ARG:0 = MASTER, ARG:1 = TARGET ;ARG、ARGS,関数中で#DIM,#DIMSを用いて定義したプライベート変数以外の引数に初期値を設定しても無視されます。 ;そのため想定通りの動作ができません。 @FOOBAR, X = 5, Y = 4 ==== 引数の参照渡し ==== ver1.810から、参照型変数を仮引数にすることで引数の参照渡しができるようになりました。\\ 参照型変数の定義方法は[[erabasicリファレンス_変数・定数・配列#変数の宣言・有効範囲|参照型変数の項]]を確認してください。\\ @SYSTEM_TITLE A = 0 CALL TEST(A) B = 1 CALL TEST(B) PRINTFORML A == {A} PRINTFORML B == {B} WAIT @TEST(HOGE) #DIM REF HOGE HOGE = 100 RETURN <実行結果> A == 100 B == 100 上の例で関数TESTは仮引数に参照型変数を持ちます。\\ 1回目にTESTが呼ばれたとき、HOGEは実引数Aを参照するようになります。\\ 関数TEST中でHOGE = 100とすることで参照先の変数Aに100が代入されるので1回目のPRINTFORMLの結果は100になります。\\ 同様に2回目のTESTが呼ばれると変数Bに100が代入され、2回目のPRINTFORMLの結果も100になります。\\ ===== 属性 ===== 関数の仕様や動作を決定するプリプロセッサです。\\ 関数に#から始まるプリプロセッサを記述する場合、関数の直下にしなくてはなりません。\\ ===== #ONLY ===== イベント関数専用の属性です。\\ #ONLYが指定されたイベント関数がある場合、その1つのみが実行され、他の同名イベント関数を実行されません。\\ また#ONLYが指定された同名イベント関数が複数ある場合も実行されるのは「最初の1つ」のみとなります。\\ ===== #FUNCTION ===== 式中関数の属性です。\\ 式中関数は通常のRETURNで終了することはできず、代わりにRETURNF <数式>で終了する必要があります。\\ 詳しくはユーザー定義の式中関数を参照してください。\\ ===== #FUNCTIONS ===== 式中関数の属性です。\\ 式中関数は通常のRETURNで終了することはできず、代わりにRETURNF <文字列式>で終了する必要があります。\\ 詳しくはユーザー定義の式中関数を参照してください。\\ ===== 定義 ===== 変数の名前やその仕様を定義するプリプロセッサです。\\ 関数に#から始まるプリプロセッサを記述する場合、関数の直下にしなくてはなりません。\\ ---- ===== ユーザー定義式中関数 ===== 「式中で使える関数」として、組み込み関数だけでなく@〜〜で定義した関数を式中で呼び出すことも可能です。\\ 「式中で使える関数」のうち組み込み関数については式中で使える関数を参照してください。\\ ==== 書式 ==== 呼び出される関数は#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ファイル中のスクリプトからだけではなく、デバッグコマンドやデバッグ用の変数ウォッチウインドウから動的に呼び出されることがあります。\\ 特に変数ウォッチは頻繁に値を更新しようとし、更新のたびにその関数を呼び出します。\\ 副作用を持つ関数はこのような呼び出しにより誤動作を起こす可能性があります。\\ ===== 命令の説明 ===== ==== CALL 関数名(,引数変数,…) ==== 関数呼び出し命令です。関数名の関数を呼び出しますが、なければエラーになります。RETURN命令もしくは関数の終端で元のCALL命令の次の行に戻ります。そのときにRESULT:0にRETURN命令で入れられた数値が入ってます ==== JUMP 関数名(,引数変数,…) ==== 関数移動命令です。関数名の関数がなければエラーを出します。あればそこに移動します。移動したら元の場所には戻って来ません。 ==== THROW ==== 強制的にエラーとし、引数に与えた文字列でエラー表示を行う命令です。\\ ==== TRYJUMP <文字列> (, 引数1, 引数2……) ==== ==== TRYCALL <文字列> (, 引数1, 引数2……) ==== ==== TRYGOTO <文字列> ==== JUMP、CALL、GOTOと同じですが、指定した関数が存在しなくともエラーになりません。\\ 指定した関数が存在しない場合は何もしません。\\ TRYJUMPとTRYCALLは引数を指定できます。詳しくは関数の「自作関数における引数指定」の項を参照してください。\\ なお、TRYGOTOで直接IF〜ELSEIF〜ELSE〜ENDIF内に入った場合、ELSEIF、ELSE、ENDIFの直前まで通常通り実行したあとに、ENDIFの次の行へ飛び処理を続行します。\\ また直接REPEAT〜REND内に入った場合、RENDの直前まで通常通り実行し、その後RENDを無視して次の行から処理を続行します。\\ これらの処理はGOTOや他のGOTO系命令と同様の処理です。その他のEmueraで追加されたループ・分岐構文についてはこのページの「ループ・分岐構文」「TRYC系」の項を参照してください。\\ === 基本の動作 === **TRYCALL 関数名(,引数変数,…)** 関数呼び出し命令です。関数名が存在すればCALL命令同様に働きますが、存在しなければエラーは出さずに何もしません。 **TRYGOTO ラベル** ラベル名の次の箇所まで移動する命令ですが、ラベルがなければ何もしません。あとの制限はGOTO命令と同様です。 **TRYJUMP 関数名(,引数変数,…)** 関数移動命令です。関数名が存在すればJUMP命令同様に働きますが、存在しなければエラーは出さずに何もしません。あとの制限はJUMP命令と同様です。 ==== JUMPFORM <書式付文字列> (, 引数1, 引数2……) ==== ==== CALLFORM <書式付文字列> (, 引数1, 引数2……) ==== ==== GOTOFORM <書式付文字列> ==== JUMP、CALL、GOTOと同じですが、PRINTFORMなどと同じ形式で関数名を指定できます。\\ CALLFORM KOJO_{NO:TARGET}_{SELECTCOM} のような使い方ができます。 JUMPFORMとCALLFORMは引数を指定できます。詳しくは関数の「自作関数における引数指定」の項を参照してください。\\ なお、GOTOFORMで直接ループ・分岐構文内に入った場合については「TRYGOTO」やこのページの「ループ・分岐構文」「TRYC系」の項を参照してください。\\ ==== TRYJUMPFORM <書式付文字列> (, 引数1, 引数2……) ==== ==== TRYCALLFORM <書式付文字列> (, 引数1, 引数2……) ==== ==== TRYGOTOFORM <書式付文字列> ==== JUMP、CALL、GOTOと同じですが、PRINTFORMなどと同じ形式で関数名を指定でき、関数が存在しなくてもエラーになりません。\\ TRYJUMPFORMとTRYCALLFORMは引数を指定できます。詳しくは関数の「自作関数における引数指定」の項を参照してください。\\ なお、TRYGOTOFORMで直接ループ・分岐構文内に入った場合については「TRYGOTO」やこのページの「ループ・分岐構文」「TRYC系」の項を参照してください。\\ ==== CALLF <文字列> (, 引数1, 引数2……) ==== ==== CALLFORMF <書式付文字列> (, 引数1, 引数2……) ==== 以下、私家改造版更新履歴より、\\ 式中関数を返り値無視で呼び出す命令CALLF、CALLFORMF実装  書式:CALLF 関数名, 引数1, ....     (式中関数ですが、普通の関数の引数書式で呼び出してください)  内容:式中関数を通常の関数扱いで呼び出す、返り値は破棄される   疑似SETTERを作りたくてやった、今は反省している 当然だがRESULTやRESULTSは呼んだ式中関数内で操作していない限り、変化しない。 ==== TRYCJUMP <文字列> (, 引数1, 引数2……) ==== ==== TRYCCALL <文字列> (, 引数1, 引数2……) ==== ==== TRYCGOTO <文字列> ==== ==== TRYCJUMPFORM <書式付文字列> (, 引数1, 引数2……) ==== ==== TRYCCALLFORM <書式付文字列> (, 引数1, 引数2……) ==== ==== TRYCGOTOFORM <書式付文字列> ==== ==== CATCH\\ ENDCATCH ==== 拡張書式:TRYC系関数呼び出し〜CATCH〜ENDCATCH\\  (TRYC系はTRY系関数と同様の関数系が用意されてます)\\ 内容:TRYC系の関数呼び出し時に関数が見つからなかった場合の挙動を制御\\  文法としてはIF〜ELSE〜ENDIFと同様になりました(違いは関数があった場合の処理がなくてもよいこと)\\ そのため、GOTO等の命令で直接TRYC系〜CATCH〜ENDCATCH内に入った場合、IF〜ELSEIF〜ELSE〜ENDIFと同様に\\ CATCH、ENDCATCHの直前まで通常通り実行したあとに、ENDCATCHの次の行へ飛び処理を続行します。\\ また、TRYCGOTO・TRYCGOTOFORMで直接ループ・分岐構文内に入った場合については「TRYGOTO」やこのページの「ループ・分岐構文」の項を参照してください。\\ TRYCCALL UNKNOWN_FUNC ;存在しない関数 関数があったとき、関数処理後に行う処理(あれば、なければ省略して直CATCHでOK) CATCH 関数がなかったときに行う処理 ENDCATCH なお、入れ子可能です。\\ ==== TRYCALLLIST ==== ==== TRYJUMPLIST ==== ==== TRYGOTOLIST ==== ==== FUNC <文字列> (, 引数1, 引数2……)\\ ENDFUNC ==== 複数の関数(ラベル)を指定し、最初に見つかった関数(のみ)を呼び出すための構文です。\\ TRYLIST系〜ENDFUNC内に上記の文法以外の記述をすることはできません。\\ なお、TRYGOTOLISTで直接ループ・分岐構文内に入った場合については「TRYGOTO」やこのページの「ループ・分岐構文」「TRYC系」の項を参照してください。\\ 以下のように使用します。\\ TRYCALLLIST FUNC 関数1 FUNC 関数2 ENDFUNC FUNCで指定された関数の呼び出しを順に試み、成功すれば呼び出した後ENDFUNCへ、失敗すれば次の行のFUNC(又はENDFUNC)へ移動します。\\ これは以下のスクリプトと同等です。\\ TRYCCALL 関数1 CATCH TRYCCALL 関数2 CATCH ENDCATCH ENDCATCH ==== RETURN <数式>(, <数式>, <数式>, ...) ==== eramakerからある命令ですが、返り値に定数でない変数や数式も指定できるようになりました。\\ また、複数の返り値に対応しています。\\ 複数の返り値を指定した場合、先頭からRESULT:0、RESULT:1...という風に代入されます。\\ === 基本の動作 === **RETURN 数値変数or数値** CALLで呼び出された関数から元に戻るための命令です。これが省略されて関数の終端まで達したときにはRETURN 0と同様に動作します。RETURNの後ろの数値はRESULT:0に代入されます。 ==== RETURNFORM <書式付文字列>(, <書式付文字列>, <書式付文字列>, ...) ==== RETURNの亜種です。\\ 引数に指定された書式付文字列を数式として解析し、RETURNを行います。\\ 例えば、以下のようなことができます。\\ A = 100 CALL TEST PRINTFORMW RESULT == {RESULT} @TEST STR = A * 10 RETURNFORM %STR% RETURNと異なり、%は剰余演算子ではなく文字列式の開始とみなされるので注意してください。\\ ;OK。Aの下2ケタを返す。 RETURN A % 100 ;エラー。%以降を文字列式として読もうとするので。 RETURNFORM A % 100 また、複数の返り値に対応しています。\\ 複数の返り値を指定した場合、先頭からRESULT:0、RESULT:1...という風に代入されます。\\ ==== RETURNF <式> ==== #FUNCTIONまたは#FUNCTIONS属性を持つ関数専用の命令です。\\ 詳細はユーザー定義の式中関数を参照してください。\\ 複数の返り値には対応していません。\\ ==== CALLEVENT <文字列> ==== イベント関数をイベント関数として呼び出します。 引数を与えることはできません。 またイベント関数中やイベント関数から呼び出された関数中で使用することもできません。