ファンクションコール

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 ステートメント内。

  • READFINDSELECTUPDATE および STORE などのデータベースアクセスステートメント内。

  • AT BREAK または IF BREAK ステートメント内。

  • AVERSUM および *TRIM などの Natural システム関数の引数として。

  • 配列インデックス表現内。

  • ファンクションコールのパラメータとして。

ファンクションコールが INPUT ステートメントで使用される場合、戻り値は定数値として処理されます。これにより、属性 AD=O が自動的に割り当てられ、このフィールドを書き込み保護に設定します(出力の場合のみ)。

構文説明

オペランド定義テーブル:

オペランド 構文要素 フォーマット オペランド参照 ダイナミック定義
function-name   S A     A  U                     ×

構文要素の説明:

構文要素 説明
function-name
関数名:

function-name は次のいずれかになります。

  • DEFINE FUNCTION ステートメントで参照として呼び出される関数の名前、または

  • 実行時に呼び出された関数の名前を含む英数字の変数の名前。この変数は、DEFINE PROTOTYPE ステートメントの VARIABLE キーワードによるプロトタイプ定義で参照する必要があります。このプロトタイプに正しいパラメータと結果フィールド定義が含まれていない場合は、別のプロトタイプを prototype-clause で割り当てることができます。

prototype-clause
プロトタイプ節:

プロトタイプ節(PT=)を参照してください。

intermediate-result-clause
中間結果節:

中間結果節(IR=)を参照してください。

parameter
パラメータ指定:

parameter」を参照してください。

array-index-expression
配列インデックス表記:

ファンクションコールによって返された結果が配列の場合、インデックス表記を指定して、要求された配列のオカレンスに対応する必要があります。

詳しくは、「ユーザー定義変数」の「インデックス表記」を参照してください。

prototype-clause (PT=)

PT= prototype-name

Natural では、コンパイル時にファンクションコールを解決するためにパラメータ定義と関数の結果が必要です。function-name(呼び出された関数に対して定義されたパラメータまたは関数の結果)と一致するプロトタイプがない場合は、prototype-clause で一致するプロトタイプを割り当てることができます。この場合、参照されるプロトタイプが代わりに配置され、パラメータと関数の結果の定義を解決するために使用されます。参照されているプロトタイプで宣言されている function-name は無視されます。

構文要素の説明:

構文要素 説明
prototype-name
プロトタイプ名:

prototype-name は次のいずれかになります。

  • 結果とパラメータレイアウトを使用するプロトタイプの名前、または

  • ファンクションコールで function-name として指定された英数字フィールドの名前。このフィールドに、実行時に呼び出される関数の名前が含まれている必要があります。

    フィールド名では、配列の添字表現は指定しないでください。

intermediate-result-clause (IR=)

IR=

format-length [/array-definition]

[(array-definition)] HANDLE OF OBJECT
(

A
U
B

[/array-definition]) DYNAMIC

関数のカタログされたオブジェクトとプロトタイプ定義のいずれも使用できない場合、この節を使用してファンクションコールの結果値の format-length/array definition を指定できます。このファンクションコールにプロトタイプを使用できる場合、または呼び出された関数のカタログされたオブジェクトが存在する場合、intermediate-result-clause で指定された結果値フォーマットのデータ転送の互換性がチェックされます。

構文要素の説明:

構文要素 説明
format-length
フォーマット/長さの定義:

フィールドのフォーマットおよび長さ。

ユーザー定義変数のフォーマットおよび長さの定義については、「ユーザー定義変数のフォーマットおよび長さ」を参照してください。

array-definition
配列の次元の定義:

array-definition には、配列定義の次元の下限と上限を定義します。

ステートメント』ドキュメントの「配列の次元の定義」を参照してください。

HANDLE OF OBJECT
オブジェクトのハンドル:

NaturalX とともに使用します。

詳細については、『プログラミングガイド』の「NaturalX」を参照してください。

AB または U
データフォーマット:

使用可能なフォーマットは、ダイナミック変数に対する英数字、バイナリ、または Unicode です。

DYNAMIC
ダイナミック変数:

フィールドは DYNAMIC として定義できます。

ダイナミック変数の処理の詳細については、「ダイナミック変数およびフィールドについて」を参照してください。

parameter

nX

 

 

M
O
A

 

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
省略されるパラメータ:

表記 nX を使用して、次の n パラメータを省略するように指定できます。例えば、1X は次のパラメータを省略し、3X は次のパラメータを 3 つ省略します。これは、次の n パラメータに、関数に渡す値がないことを意味します。

省略されるパラメータは、関数の DEFINE DATA PARAMETER ステートメントでキーワード OPTIONAL を使用して定義する必要があります。OPTIONAL は、値を呼び出し側オブジェクトからこのようなパラメータに渡すこともできるということを意味します。

AD=
属性定義:

operand が変数の場合は、次のいずれかの方法でマークすることができます。

AD=O
変更不可:

セッションパラメータ「AD=O」を参照してください。

注意:
内部的に、AD=OBY VALUE と同様に処理されます(DEFINE DATA ステートメントの説明の parameter-data-definition を参照)。

AD=M
変更可:

セッションパラメータ「AD=M」を参照してください。

これはデフォルト設定です。

AD=A
入力のみ:

セッションパラメータ「AD=A」を参照してください。

注意:
operand が定数の場合は、属性定義 AD を明示的に指定することはできません。定数には常に AD=O が適用されます。

プログラム例 FUNCEX01 では、関数 F#ADDITIONF#CHARF#EVEN および F#TEXT を使用します。

このセクションに示すすべてのサンプルソースは、Natural SYSEXPG システムライブラリのソースオブジェクトおよびカタログ化オブジェクトとして提供されます。

呼び出し元のプログラム FUNCEX01:

** 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   

プログラムの出力 FUNCEX01

Sum of #B,#C      5        
Character A found                             
     2 is an even number            
*** Hello world ***                 
Good morning 

呼び出される関数 F#ADDITION

関数 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

関数 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

関数 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

関数 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 つのオプションがあります。

  1. 以前に DEFINE PROTOTYPE ステートメントが実行されていない場合は、呼び出された関数のカタログ化オブジェクト(使用可能な場合)からパラメータと結果の指定を暗黙的に取得します。

    この方法では、最小限のプログラミング作業で済みます。

  2. DEFINE PROTOTYPE ステートメントを使用します。呼び出された関数のカタログ化オブジェクトが使用できない場合、またはファンクション名がコンパイル時に不明な場合は、DEFINE PROTOTYPE ステートメントを使用する必要があります。つまり、ファンクション名の代わりに英数字変数の名前をファンクションコールで指定します。

  3. ファンクションコールで明示的なIR=節を指定します。

最初の 2 つの方法は、パラメータのフォーマット、長さ、および配列構造と関数の結果の完全検証で構成されます。

ファンクションコールの追加の節

DEFINE PROTOTYPE ステートメントとカタログされたファンクションオブジェクトのいずれも存在しない場合は、ファンクションコールで次の節を使用できます。

  • IR=節では、関数の結果のフォーマット/長さ/配列構造を指定します。

    この節では、コンパイラが結果フィールド(ファンクションコールを含むステートメントで使用される中間結果)で想定するフォーマット/長さ/配列構造を決定します。ファンクションコールにプロトタイプ定義が使用可能な場合、(IR=)節はプロトタイプの指定を上書きします。

    IR=)節はパラメータチェックを強制しません。

  • PT=節では、ファンクション名以外の名前を持つ、あらかじめ定義されたプロトタイプを使用します。この節は、参照される名前の DEFINE PROTOTYPE ステートメントを使用して、パラメータと関数の結果を検証します。

    次の例では、関数 #MULT が呼び出されますが、#ADD という名前のプロトタイプのパラメータおよび結果の指定が適用されます。

    #I := #MULT(<(PT=#ADD) 2 , 3>)

パラメータと関数の結果の検証

検出された次の最初の定義は、指定されたパラメータをチェックするために使用されます。

  • (PT=) 節で参照されるプロトタイプ定義。

  • プロトタイプ名がファンクションコールで使用されるファンクション名と一致する DEFINE PROTOTYPE ステートメントのプロトタイプ定義。

  • DEFINE FUNCTION ステートメントとともに提供されるカタログされたファンクションオブジェクトのパラメータ指定。

上記のいずれも指定されていない場合、パラメータの検証は実行されません。これにより、構文エラーを受け取らずに、ファンクションコールのパラメータの数とレイアウトを指定するオプションが提供されます。

検出された次の最初の定義は、関数の結果をチェックするために使用されます。

  • IR=節で提供されている定義。

  • (PT=)節で参照されるプロトタイプ内の RETURNS の定義。

  • プロトタイプ名がファンクションコールで使用されるファンクション名と一致する 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