| function-name |
(< [([prototype-clause] [intermediate-result-clause])]
|
[parameter] [,[parameter]] ... >) |
| [array-index-expression] |
構文図で使用されている記号については、「構文記号」を参照してください。
関連ステートメント:DEFINE
PROTOTYPE | DEFINE
FUNCTION
このドキュメントでは、次のトピックについて説明します。
ファンクションコールは、タイプファンクションの Natural オブジェクトを呼び出します。
関数は、パラメータ、ローカル変数、およびアプリケーション独立変数、使用する結果値、関数の呼び出し時に実行されるステートメントを含む DEFINE FUNCTION ステートメントで定義します。
関数は、次のいずれかを指定して呼び出します。
DEFINE FUNCTION ステートメントで定義されたファンクション名、または
実行時に関数の名前が含まれている英数字の変数。この場合、VARIABLE キーワードで DEFINE PROTOTYPE ステートメント内の変数を参照する必要があります。
ファンクションコールは、読み取り専用オペランドではなく、Natural ステートメント内で使用できます。この場合、関数は結果を返す必要があります。結果は、同じ値を含むフィールドのようなステートメントによって処理されます。
Natural ステートメントの代わりにファンクションコールを使用することもできます。この場合、関数は結果値を返す必要はありません。返された場合、値の結果は破棄されます。
ファンクションコールは、以下の状況には使用できません。
オペランド値が Natural ステートメントによって変更される位置。例:
MOVE 1 TO #FCT(<..>);
DEFINE
DATA ステートメント内。
配列インデックス表現内。
ファンクションコールのパラメータとして。
ファンクションコールが INPUT ステートメントで使用される場合、戻り値は定数値として処理されます。これにより、属性 AD=O が自動的に割り当てられ、このフィールドを書き込み保護に設定します(出力の場合のみ)。
オペランド定義テーブル:
| オペランド | 構文要素 | フォーマット | オペランド参照 | ダイナミック定義 | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
function-name |
S | A | A | U | ○ | × | |||||||||||||
構文要素の説明:
| 構文要素 | 説明 |
|---|---|
function-name |
関数名:
|
prototype-clause |
プロトタイプ節:
プロトタイプ節(PT=)を参照してください。 |
intermediate-result-clause |
中間結果節:
中間結果節(IR=)を参照してください。 |
parameter |
パラメータ指定:
「 |
array-index-expression |
配列インデックス表記:
ファンクションコールによって返された結果が配列の場合、インデックス表記を指定して、要求された配列のオカレンスに対応する必要があります。 詳しくは、「ユーザー定義変数」の「インデックス表記」を参照してください。 |
PT= prototype-name |
Natural では、コンパイル時にファンクションコールを解決するためにパラメータ定義と関数の結果が必要です。function-name(呼び出された関数に対して定義されたパラメータまたは関数の結果)と一致するプロトタイプがない場合は、prototype-clause で一致するプロトタイプを割り当てることができます。この場合、参照されるプロトタイプが代わりに配置され、パラメータと関数の結果の定義を解決するために使用されます。参照されているプロトタイプで宣言されている function-name は無視されます。
構文要素の説明:
| 構文要素 | 説明 |
|---|---|
prototype-name |
プロトタイプ名:
|
IR= |
|
format-length [/array-definition] |
|
||||||
[(array-definition)] HANDLE OF OBJECT |
|||||||||
| ( |
|
|
[/array-definition]) DYNAMIC |
||||||
関数のカタログされたオブジェクトとプロトタイプ定義のいずれも使用できない場合、この節を使用してファンクションコールの結果値の format-length/array
definition を指定できます。このファンクションコールにプロトタイプを使用できる場合、または呼び出された関数のカタログされたオブジェクトが存在する場合、intermediate-result-clause で指定された結果値フォーマットのデータ転送の互換性がチェックされます。
構文要素の説明:
| 構文要素 | 説明 |
|---|---|
format-length |
フォーマット/長さの定義:
フィールドのフォーマットおよび長さ。 ユーザー定義変数のフォーマットおよび長さの定義については、「ユーザー定義変数のフォーマットおよび長さ」を参照してください。 |
array-definition |
配列の次元の定義:
array-definition には、配列定義の次元の下限と上限を定義します。 『ステートメント』ドキュメントの「配列の次元の定義」を参照してください。 |
HANDLE OF
OBJECT |
オブジェクトのハンドル:
NaturalX とともに使用します。 詳細については、『プログラミングガイド』の「NaturalX」を参照してください。 |
A、B または U |
データフォーマット:
使用可能なフォーマットは、ダイナミック変数に対する英数字、バイナリ、または Unicode です。 |
DYNAMIC |
ダイナミック変数:
フィールドは ダイナミック変数の処理の詳細については、「ダイナミック変数およびフィールドについて」を参照してください。 |
|
|
nX |
|
|||||||
|
|
|
|
|
|
|||||
| operand | (AD= |
) |
|||||||
関数にデータ値を渡すために、1 つまたは複数のパラメータを指定できます。関数内の DEFINE DATA
PARAMETER の定義に応じて、定数値または変数として提供できます。
関数のパラメータに適用される語義と構文の規則は、サブプログラムのパラメータセクションで説明されているものと同じです。CALLNAT ステートメントの「パラメータ」を参照してください。
オペランド定義テーブル:
| オペランド | 構文要素 | フォーマット | オペランド参照 | ダイナミック定義 | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
operand |
C | S | A | G | N * | A | N | P | I | F | B | D | T | L | C | G | O | ○ | × | ||
注意:
アスタリスクが付いているオプションは、Windows および UNIX プラットフォームにのみ適用されます。
構文要素の説明:
| 構文要素 | 説明 | |
|---|---|---|
nX |
省略されるパラメータ:
表記 省略されるパラメータは、関数の |
|
AD= |
属性定義:
|
|
AD=O |
変更不可:
セッションパラメータ「 注意: |
|
AD=M |
変更可:
セッションパラメータ「 これはデフォルト設定です。 |
|
AD=A |
入力のみ:
セッションパラメータ「 |
|
|
注意: |
||
プログラム例 FUNCEX01 では、関数 F#ADDITION、F#CHAR、F#EVEN および F#TEXT を使用します。
このセクションに示すすべてのサンプルソースは、Natural SYSEXPG システムライブラリのソースオブジェクトおよびカタログ化オブジェクトとして提供されます。
** Example 'FUNCEX01': Function call (Program)
************************************************************************
DEFINE DATA LOCAL
1 #NUM (I2) INIT <5>
1 #A (I2) INIT <1>
1 #B (I2) INIT <2>
1 #C (I2) INIT <3>
1 #CHAR (A1) INIT <'A'>
END-DEFINE
*
IF #NUM = F#ADDITION(<#A,#B,#C>) /* Function with three parameters.
WRITE 'Sum of #A,#B,#C' #NUM
ELSE
IF #NUM = F#ADDITION(<1X,#B,#C>) /* Function with optional parameters.
WRITE 'Sum of #B,#C' #NUM
END-IF
END-IF
*
DECIDE ON FIRST #CHAR
VALUE F#CHAR (<>)(1) /* Function with result array.
WRITE 'Character A found'
VALUE F#CHAR (<>)(2)
WRITE 'Character B found'
NONE
IGNORE
END-DECIDE
*
IF F#EVEN(<#B>) /* Function with logical result value.
WRITE #B 'is an even number'
END-IF
*
F#TEXT(<'Hello', '*'>) /* Function used as a statement.
*
WRITE F#TEXT(<(IR=A12) 'Good'>) /* Function with intermediate result.
*
END
FUNCEX01Sum of #B,#C 5
Character A found
2 is an even number
*** Hello world ***
Good morning
関数 F#ADDITION は、サンプル関数 FUNCEX02 で定義されています。
** Example 'FUNCEX02': Function call (Function)
************************************************************************
DEFINE FUNCTION F#ADDITION
RETURNS (I2)
DEFINE DATA PARAMETER
1 #PARM1 (I2) OPTIONAL
1 #PARM2 (I2) OPTIONAL
1 #PARM3 (I2) OPTIONAL
END-DEFINE
/*
RESET F#ADDITION
IF #PARM1 SPECIFIED
F#ADDITION := F#ADDITION + #PARM1
END-IF
IF #PARM2 SPECIFIED
F#ADDITION := F#ADDITION + #PARM2
END-IF
IF #PARM3 SPECIFIED
F#ADDITION := F#ADDITION + #PARM3
END-IF
/*
END-FUNCTION
*
END
関数 F#CHAR は、サンプル関数 FUNCEX03 で定義されています。
** Example 'FUNCEX03': Function call (Function) ************************************************************************ DEFINE FUNCTION F#CHAR RETURNS (A1/1:2) /* F#CHAR(1) := 'A' F#CHAR(2) := 'B' /* END-FUNCTION * END
関数 F#EVEN は、サンプル関数 FUNCEX04 で定義されています。
** Example 'FUNCEX04': Function call (Function)
************************************************************************
DEFINE FUNCTION F#EVEN
RETURNS (L)
DEFINE DATA
PARAMETER
1 #NUM (N4) BY VALUE
LOCAL
1 #REST (I2)
END-DEFINE
/*
DIVIDE 2 INTO #NUM REMAINDER #REST
/*
IF #REST = 0
F#EVEN := TRUE
ELSE
F#EVEN := FALSE
END-IF
/*
END-FUNCTION
*
END
関数 F#TEXT は、ライブラリ SYSEXPG のサンプル関数 FUNCEX05 で定義されています。
** Example 'FUNCEX05': Function call (Function)
************************************************************************
DEFINE FUNCTION F#TEXT
RETURNS (A20) BY VALUE
DEFINE DATA
PARAMETER
1 #TEXT1 (A5) BY VALUE
1 #TEXT2 (A1) BY VALUE OPTIONAL
LOCAL
1 #FRAME (A3)
END-DEFINE
/*
IF #TEXT2 SPECIFIED
MOVE ALL #TEXT2 TO #FRAME
/*
COMPRESS #FRAME #TEXT1 'world' #FRAME INTO F#TEXT
/*
WRITE F#TEXT
ELSE
COMPRESS #TEXT1 'morning' INTO F#TEXT
/*
END-IF
/*
END-FUNCTION
*
END
ファンクション定義に応じて、ファンクションコールは 1 つの結果フィールドを返すことがあります。これはスカラ値または配列フィールドで、ファンクションコールが組み込まれたステートメントの一時フィールドのように処理されます。結果が配列の場合、ファンクションコールの直後に必要なオカレンスに対処する
array-index-expression を続ける必要があります。
例えば、返された配列の最初のオカレンスにアクセスするには、次のようにします。
#FCT(<#A,#B>)(1)
コンパイル時にファンクションコールを正しく解決するには、コンパイラにパラメータのフォーマット、長さ、および配列構造と関数の結果が必要です。ファンクションコールで指定されたパラメータは、関数内の対応する定義と照合され、それらが一致していることが確認されます。オペランドではなくステートメント内で関数を使用する場合、関数の結果はオペランドのフォーマット、長さ、および配列構造と一致する必要があります。
この情報を提供する方法には、次の 3 つのオプションがあります。
以前に DEFINE PROTOTYPE ステートメントが実行されていない場合は、呼び出された関数のカタログ化オブジェクト(使用可能な場合)からパラメータと結果の指定を暗黙的に取得します。
この方法では、最小限のプログラミング作業で済みます。
DEFINE
PROTOTYPE ステートメントを使用します。呼び出された関数のカタログ化オブジェクトが使用できない場合、またはファンクション名がコンパイル時に不明な場合は、DEFINE
PROTOTYPE ステートメントを使用する必要があります。つまり、ファンクション名の代わりに英数字変数の名前をファンクションコールで指定します。
ファンクションコールで明示的な(IR=)節を指定します。
最初の 2 つの方法は、パラメータのフォーマット、長さ、および配列構造と関数の結果の完全検証で構成されます。
DEFINE PROTOTYPE ステートメントとカタログされたファンクションオブジェクトのいずれも存在しない場合は、ファンクションコールで次の節を使用できます。
(IR=)節では、関数の結果のフォーマット/長さ/配列構造を指定します。
この節では、コンパイラが結果フィールド(ファンクションコールを含むステートメントで使用される中間結果)で想定するフォーマット/長さ/配列構造を決定します。ファンクションコールにプロトタイプ定義が使用可能な場合、(IR=)節はプロトタイプの指定を上書きします。
(IR=)節はパラメータチェックを強制しません。
(PT=)節では、ファンクション名以外の名前を持つ、あらかじめ定義されたプロトタイプを使用します。この節は、参照される名前の DEFINE
PROTOTYPE ステートメントを使用して、パラメータと関数の結果を検証します。
次の例では、関数 #MULT が呼び出されますが、#ADD という名前のプロトタイプのパラメータおよび結果の指定が適用されます。
#I := #MULT(<(PT=#ADD) 2 , 3>)
検出された次の最初の定義は、指定されたパラメータをチェックするために使用されます。
(PT=) 節で参照されるプロトタイプ定義。
プロトタイプ名がファンクションコールで使用されるファンクション名と一致する DEFINE PROTOTYPE ステートメントのプロトタイプ定義。
DEFINE FUNCTION ステートメントとともに提供されるカタログされたファンクションオブジェクトのパラメータ指定。
上記のいずれも指定されていない場合、パラメータの検証は実行されません。これにより、構文エラーを受け取らずに、ファンクションコールのパラメータの数とレイアウトを指定するオプションが提供されます。
検出された次の最初の定義は、関数の結果をチェックするために使用されます。
(IR=)節で提供されている定義。
プロトタイプ名がファンクションコールで使用されるファンクション名と一致する DEFINE PROTOTYPE ステートメントのプロトタイプ定義。
カタログされたファンクションオブジェクトの関数の結果の指定。
上記のいずれも指定されていない場合、構文エラーが発生します。
プログラム:
** Example 'FUNCBX01': Declare result value and parameters (Program)
************************************************************************
*
DEFINE DATA LOCAL
1 #PROTO-NAME (A20)
1 #PARM1 (I4)
1 #PARM2 (I4)
END-DEFINE
*
DEFINE PROTOTYPE VARIABLE #PROTO-NAME
RETURNS (I4)
DEFINE DATA PARAMETER
1 #P1 (I4) BY VALUE OPTIONAL
1 #P2 (I4) BY VALUE
END-DEFINE
END-PROTOTYPE
*
#PROTO-NAME := 'F#MULTI'
#PARM1 := 3
#PARM2 := 5
*
WRITE #PROTO-NAME(<#PARM1, #PARM2>)
WRITE #PROTO-NAME(<1X ,5>)
*
WRITE F#MULTI(<(PT=#PROTO-NAME) #PARM1,#PARM2>)
*
WRITE F#MULTI(<(IR=N20) #PARM1, #PARM2>)
*
END
関数 F#MULTI:
** Example 'FUNCBX02': Declare result value and parameters (Function)
************************************************************************
DEFINE FUNCTION F#MULTI
RETURNS #RESULT (I4) BY VALUE
DEFINE DATA PARAMETER
1 #FACTOR1 (I4) BY VALUE OPTIONAL
1 #FACTOR2 (I4) BY VALUE
END-DEFINE
/*
IF #FACTOR1 SPECIFIED
#RESULT := #FACTOR1 * #FACTOR2
ELSE
#RESULT := #FACTOR2 * 10
END-IF
/*
END-FUNCTION
*
END
Natural ステートメント内で使用されるすべてのファンクションコールは、ステートメントの実行が開始される前に評価されます。これらはステートメントに表示される順序と同じ順序で評価されます。関数の結果値は一時フィールドに格納されます。この一時フィールドは、後でステートメントの実行のオペランドとして使用されます。
同じステートメント内で繰り返し使用される変更可能なパラメータを持つ関数を呼び出すと、次の例に示すように関数の結果が異なる可能性があります。
COMPUTE ステートメントが開始される前の変数 #I の値は 1 です。最初のステップで、関数 F#RETURN が実行されます。これにより、#I の値が 2 に変更され、関数の結果として 2 の値が返されます。その後、COMPUTE 演算が開始され、#I (2) の値と一時フィールドの値 (2) が合計され、値 4 になります。
** Example 'FUNCCX01': Parameter changed within function (Program)
************************************************************************
DEFINE DATA LOCAL
1 #I (I2) INIT <1>
1 #RESULT (I2)
END-DEFINE
*
COMPUTE #RESULT := #I + F#RETURN(<#I>) /* First evaluate function call,
/* then execute the addition.
*
WRITE '#I :' #I /
'#RESULT:' #RESULT
*
END
** Example 'FUNCCX02': Parameter changed within function (Function)
************************************************************************
DEFINE FUNCTION F#RETURN
RETURNS #RESULT (I2) BY VALUE
DEFINE DATA PARAMETER
1 #PARM1 (I2) BY VALUE RESULT
END-DEFINE
/*
#PARM1 := #PARM1 + 1 /* Increment parameter.
#RESULT := #PARM1 /* Set result value.
/*
END-FUNCTION
*
END
FUNCCX01 の出力:
#I : 2 #RESULT: 4
また、ファンクションコールをステートメントに組み込むことなく、Natural ステートメントの代わりにファンクションコールを使用することもできます。この場合、ファンクションコールは結果値を返す必要はありません。返された場合、結果値は破棄されます。
次の例に示すように、ファンクションコールと前のステートメントをセミコロン(;)で区切ることによって、このようなファンクションコールが前のステートメントの一部とみなされることを回避できます。
プログラム:
** Example 'FUNCDX01': Using a function as a statement (Program)
************************************************************************
DEFINE DATA LOCAL
1 #A (I4) INIT <1>
1 #B (I4) INIT <2>
END-DEFINE
*
*
WRITE 'Write:' #A #B
F#PRINT-ADD(< 2,3 >) /* Function call belongs to operand list
/* immediately preceding it.
*
WRITE // '*************************' //
*
WRITE 'Write:' #A #B; /* Semicolon separates operands and function.
F#PRINT-ADD(< 2,3 >) /* Function call does not belong to the
/* operand list.
*
END
機能:
** Example 'FUNCDX02': Using a function as a statement (Function)
************************************************************************
DEFINE FUNCTION F#PRINT-ADD
RETURNS (I4)
DEFINE DATA PARAMETER
1 #SUMMAND1 (I4) BY VALUE
1 #SUMMAND2 (I4) BY VALUE
END-DEFINE
/*
F#PRINT-ADD := #SUMMAND1 + #SUMMAND2 /* Result of function call.
WRITE 'Function call:' F#PRINT-ADD
/*
END-FUNCTION
*
END
プログラム FUNCDX01 の出力:
Function call: 5 Write: 1 2 5 ************************* Write: 1 2 Function call: 5