Function Definitions<indexterm> <primary>Functions</primary> </indexterm> (Parameter Passing<indexterm> <primary><emphasis role="bold">Parameter Passing</emphasis></primary> </indexterm>) All of the basic Definition types can also become functions by defining them to accept passed parameters (arguments arguments ). The fact that it receives parameters doesn't change the essential nature of the Definition's type, it simply makes it more flexible. Parameter definitions always appear in parentheses attached to the Definition's name. You may define the function to receive as many parameters as needed to create the desired functionality by simply separating each succeeding parameter definition with a comma. The format of parameter definitions is as follows: DefinitionName( [ ValueType ] AliasName [ =DefaultValue ] ) := expression; ValueType Optional. Specifies the type of data being passed. If omitted, the default is INTEGER (see Value Types Value Types ). This also may include the CONST keyword (see CONST CONST ) to indicate that the passed value will always be treated as a constant. AliasName Names the parameter for use in the expression. DefaultValue Optional. Provides the value to use in the expression if the parameter is omitted. The DefaultValue may be the keyword ALL if the ValueType is SET (see the SET SET keyword) to indicate all possible values for that type of set, or empty square brackets square brackets ([ ]) to indicate no possible value for that type of set. expression The function's operation for which the parameters are used. Simple Value Type Parameters If the optional ValueType is any of the simple types (BOOLEAN, INTEGER, REAL, DECIMAL, STRING, QSTRING, UNICODE, DATA, VARSTRING, VARUNICODE), the ValueType may include the CONST keyword (see CONST) to indicate that the passed value will always be treated as a constant (typically used only in ECL prototypes of external functions). ValueDefinition := 15; FirstFunction(INTEGER x=5) := x + 5; //takes an integer parameter named "x" and "x" is used in the //arithmetic expression to indicate the usage of the parameter SecondDefinition := FirstFunction(ValueDefinition); // The value of SecondDefinition is 20 ThirdDefinition := FirstFunction(); // The value of ThirdDefinition is 10, omitting the parameter SET Parameters The DefaultValue for SET parameters SET parameters may be a default set of values, the keyword ALL to indicate all possible values for that type of set, or empty square brackets ([ ]) to indicate no possible value for that type of set (and empty set). SET OF INTEGER1 SetValues := [5,10,15,20]; IsInSetFunction(SET OF INTEGER1 x=SetValues,y) := y IN x; OUTPUT(IsInSetFunction([1,2,3,4],5)); //false OUTPUT(IsInSetFunction(,5)); // true Passing DATASET Parameters Passing a DATASET or a derived recordset as a parameter may be accomplished using the following syntax: DefinitionName( DATASET DATASET parameter ( recstruct ) AliasName ) := expression; The required recstruct names the RECORD structure that defines the layout of fields in the passed DATASET parameter. The recstruct may alternatively use the RECORDOF function. The required AliasName names the dataset for use in the function and is used in the Definition's expression to indicate where in the operation the passed parameter is to be used. See the DATASET as a Value Type discussion in the DATASET documentation for further examples. MyRec := {STRING1 Letter}; SomeFile := DATASET([{'A'},{'B'},{'C'},{'D'},{'E'}],MyRec); FilteredDS(DATASET(MyRec) ds) := ds(Letter NOT IN ['A','C','E']); //passed dataset referenced as “ds” in expression OUTPUT(FilteredDS(SomeFile)); Passing DICTIONARY Parameters Passing a DICTIONARY as a parameter may be accomplished using the following syntax: DefinitionName( DICTIONARY DICTIONARY parameter ( structure ) AliasName ) := expression; The required structure parameter is the RECORD structure that defines the layout of fields in the passed DICTIONARY parameter (usually defined inline). The required AliasName names the DICTIONARY for use in the function and is used in the Definition's expression to indicate where in the operation the passed parameter is to be used. See the DICTIONARY as a Value Type discussion in the DICTIONARY documentation. rec := RECORD STRING10 color; UNSIGNED1 code; STRING10 name; END; Ds := DATASET([{'Black' ,0 , 'Fred'}, {'Brown' ,1 , 'Seth'}, {'Red' ,2 , 'Sue'}, {'White' ,3 , 'Jo'}], rec); DsDCT := DICTIONARY(DS,{color => DS}); DCTrec := RECORD STRING10 color => UNSIGNED1 code, STRING10 name, END; InlineDCT := DICTIONARY([{'Black' => 0 , 'Fred'}, {'Brown' => 1 , 'Sam'}, {'Red' => 2 , 'Sue'}, {'White' => 3 , 'Jo'} ], DCTrec); MyDCTfunc(DICTIONARY(DCTrec) DCT,STRING10 key) := DCT[key].name; MyDCTfunc(InlineDCT,'White'); //Jo MyDCTfunc(DsDCT,'Brown'); //Seth Passing Typeless Parameters Passing parameters of any type may be accomplished using the keyword ANY ANY as the passed value type: DefinitionName ( ANY AliasName ) := expression; a := 10; b := 20; c := '1'; d := '2'; e := '3'; f := '4'; s1 := [c,d]; s2 := [e,f]; ds1 := DATASET(s1,{STRING1 ltr}); ds2 := DATASET(s2,{STRING1 ltr}); MyFunc(ANY l, ANY r) := l + r; MyFunc(a,b); //returns 30 MyFunc(a,c); //returns '101' MyFunc(c,d); //returns '12' MyFunc(s1,s2); //returns a set: ['1','2','3','4'] MyFunc(ds1,ds2); //returns 4 records: '1', '2', '3', and '4' Passing Function Parameters Passing a Function as a parameter may be accomplished using either of the following syntax options as the ValueType for the parameter: FunctionName(parameters) PrototypeName FunctionName The name of a function, the type of which may be passed as a parameter. parameters The parameter definitions for the FunctionName parameter. PrototypeName The name of a previously defined function to use as the type of function that may be passed as a parameter. The following code provides examples of both methods: //a Function prototype: INTEGER actionPrototype(INTEGER v1, INTEGER v2) := 0; INTEGER aveValues(INTEGER v1, INTEGER v2) := (v1 + v2) DIV 2; INTEGER addValues(INTEGER v1, INTEGER v2) := v1 + v2; INTEGER multiValues(INTEGER v1, INTEGER v2) := v1 * v2; //a Function prototype using a function prototype: INTEGER applyPrototype(INTEGER v1, actionPrototype actionFunc) := 0; //using the Function prototype and a default value: INTEGER applyValue2(INTEGER v1, actionPrototype actionFunc = aveValues) := actionFunc(v1, v1+1)*2; //Defining the Function parameter inline, witha default value: INTEGER applyValue4(INTEGER v1, INTEGER actionFunc(INTEGER v1,INTEGER v2) = aveValues) := actionFunc(v1, v1+1)*4; INTEGER doApplyValue(INTEGER v1, INTEGER actionFunc(INTEGER v1, INTEGER v2)) := applyValue2(v1+1, actionFunc); //producing simple results: OUTPUT(applyValue2(1)); // 2 OUTPUT(applyValue2(2)); // 4 OUTPUT(applyValue2(1, addValues)); // 6 OUTPUT(applyValue2(2, addValues)); // 10 OUTPUT(applyValue2(1, multiValues)); // 4 OUTPUT(applyValue2(2, multiValues)); // 12 OUTPUT(doApplyValue(1, multiValues)); // 12 OUTPUT(doApplyValue(2, multiValues)); // 24 //A definition taking function parameters which themselves //have parameters that are functions... STRING doMany(INTEGER v1, INTEGER firstAction(INTEGER v1, INTEGER actionFunc(INTEGER v1,INTEGER v2)), INTEGER secondAction(INTEGER v1, INTEGER actionFunc(INTEGER v1,INTEGER v2)), INTEGER actionFunc(INTEGER v1,INTEGER v2)) := (STRING)firstAction(v1, actionFunc) + ':' + (STRING)secondaction(v1, actionFunc); OUTPUT(doMany(1, applyValue2, applyValue4, addValues)); // produces "6:12" OUTPUT(doMany(2, applyValue4, applyValue2,multiValues)); // produces "24:12" Passing NAMED Parameters Passing values to a function defined to receive multiple parameters, many of which have default values (and are therefore omittable), is usually accomplished by “counting commas” to ensure that the values you choose to pass are passed to the correct parameter by the parameter's position in the list. This method becomes untenable when there are many optional parameters. The easier method is to use the following NAMED parameter syntax, which eliminates the need to include extraneous commas as place holders to put the passed values in the proper parameters: Attr := FunctionName( [ NAMED NAMED ] AliasName := value ); NAMED Optional. Required only when the AliasName clashes with a reserved word. AliasName The names of the parameter in the definition's function definition. value The value to pass to the parameter. This syntax is used in the call to the function and allows you to pass values to specific parameters by their AliasName, without regard for their position in the list. All unnamed parameters passed must precede any NAMED parameters. outputRow(BOOLEAN showA = FALSE, BOOLEAN showB = FALSE, BOOLEAN showC = FALSE, STRING aValue = 'abc', INTEGER bValue = 10, BOOLEAN cValue = TRUE) := OUTPUT(IF(showA,' a='+aValue,'')+ IF(showB,' b='+(STRING)bValue,'')+ IF(showc,' c='+(STRING)cValue,'')); outputRow(); //produce blanks outputRow(TRUE); //produce "a=abc" outputRow(,,TRUE); //produce "c=TRUE" outputRow(NAMED showB := TRUE); //produce “b=10” outputRow(TRUE, NAMED aValue := 'Changed value'); //produce “a=Changed value” outputRow(,,,'Changed value2',NAMED showA := TRUE); //produce "a=Changed value2" outputRow(showB := TRUE); //produce “b=10” outputRow(TRUE, aValue := 'Changed value'); outputRow(,,,'Changed value2',showA := TRUE);