[resulttype] funcname ( parameterlist ) := FUNCTION
code
RETURN retval;
END;
The FUNCTION structure allows you to pass parameters to a set of related attribute definitions. This makes it possible to pass parameters to an attribute that is defined in terms of other non-exported attributes without the need to parameterise all of those as well.
Side-effect actions contained in the code of the FUNCTION must have definition names that must be referenced by the WHEN function to execute.
Example:
EXPORT doProjectChild(parentRecord l,UNSIGNED idAdjust2) := FUNCTION
newChildRecord copyChild(childRecord l) := TRANSFORM
SELF.person_id := l.person_id + idAdjust2;
SELF := l;
END;
RETURN PROJECT(CHOOSEN(l.children, numChildren),copyChild(LEFT));
END;
//And called from
SELF.children := doProjectChild(l, 99);
//**********************************
EXPORT isAnyRateGE(STRING1 rate) := FUNCTION
SetValidRates := ['0','1','2','3','4','5','6','7','8','9'];
IsValidTradeRate := ValidDate(Trades.trd_drpt) AND
Trades.trd_rate >= rate AND
Trades.trd_rate IN SetValidRates;
ValidPHR := Prev_rate(phr_grid_flag = TRUE,
phr_rate IN SetValidRates,
ValidDate(phr_date));
IsPHRGridRate := EXISTS(ValidPHR(phr_rate >= rate,
AgeOf(phr_date)<=24));
IsMaxPHRRate := MAX(ValidPHR(AgeOf(phr_date) > 24),
Prev_rate.phr_rate) >= rate;
RETURN IsValidTradeRate OR IsPHRGridRate OR IsMaxPHRRate;
END;
//*************************************************************
//a FUNCTION with side-effect Action
namesTable := FUNCTION
namesRecord := RECORD
STRING20 surname;
STRING10 forename;
INTEGER2 age := 25;
END;
o := OUTPUT('namesTable used by user <x>');
ds := DATASET([{'x','y',22}],namesRecord);
RETURN WHEN(ds,O);
END;
z := namesTable : PERSIST('z');
//the PERSIST causes the side-effect action to execute only when the PERSIST is re-built
OUTPUT(z);
//*************************************************************
//a coordinated set of 3 examples
NameRec := RECORD
STRING5 title;
STRING20 fname;
STRING20 mname;
STRING20 lname;
STRING5 name_suffix;
STRING3 name_score;
END;
MyRecord := RECORD
UNSIGNED id;
STRING uncleanedName;
NameRec Name;
END;
ds := DATASET('RTTEST::RowFunctionData', MyRecord, THOR);
STRING73 CleanPerson73(STRING inputName) := FUNCTION
suffix :=[ ' 0',' 1',' 2',' 3',' 4',' 5',' 6',' 7',' 8',' 9',
' J',' JR',' S',' SR'];
InWords := Std.Str.CleanSpaces(inputName);
HasSuffix := InWords[LENGTH(TRIM(InWords))-1 ..] IN suffix;
WordCount := LENGTH(TRIM(InWords,LEFT,RIGHT)) -
LENGTH(TRIM(InWords,ALL)) + 1;
HasMiddle := WordCount = 5 OR (WordCount = 4 AND NOT HasSuffix) ;
Sp1 := Std.Str.Find(InWords,' ',1);
Sp2 := Std.Str.Find(InWords,' ',2);
Sp3 := Std.Str.Find(InWords,' ',3);
Sp4 := Std.Str.Find(InWords,' ',4);
STRING5 title := InWords[1..Sp1-1];
STRING20 fname := InWords[Sp1+1..Sp2-1];
STRING20 mname := IF(HasMiddle,InWords[Sp2+1..Sp3-1],'');
STRING20 lname := MAP(HasMiddle AND NOT HasSuffix => InWords[Sp3+1..],
HasMiddle AND HasSuffix => InWords[Sp3+1..Sp4-1],
NOT HasMiddle AND NOT HasSuffix => InWords[Sp2+1..],
NOT HasMiddle AND HasSuffix => InWords[Sp2+1..Sp3-1],
'');
STRING5 name_suffix := IF(HasSuffix,InWords[LENGTH(TRIM(InWords))-1..],'');
STRING3 name_score := '';
RETURN title + fname + mname + lname + name_suffix + name_score;
END;
//Example 1 - a transform to create a row from an uncleaned name
NameRec createRow(string inputName) := TRANSFORM
cleanedText := LocalAddrCleanLib.CleanPerson73(inputName);
SELF.title := cleanedText[1..5];
SELF.fname := cleanedText[6..25];
SELF.mname := cleanedText[26..45];
SELF.lname := cleanedText[46..65];
SELF.name_suffix := cleanedText[66..70];
SELF.name_score := cleanedText[71..73];
END;
myRecord t(myRecord l) := TRANSFORM
SELF.Name := ROW(createRow(l.uncleanedName));
SELF := l;
END;
y := PROJECT(ds, t(LEFT));
OUTPUT(y);
//Example 2 - an attribute using that transform to generate the row.
NameRec cleanedName(STRING inputName) := ROW(createRow(inputName));
myRecord t2(myRecord l) := TRANSFORM
SELF.Name := cleanedName(l.uncleanedName);
SELF := l;
END;
y2 := PROJECT(ds, t2(LEFT));
OUTPUT(y2);
//Example 3 = Encapsulate the transform inside the attribute by
// defining a FUNCTION.
NameRec cleanedName2(STRING inputName) := FUNCTION
NameRec createRow := TRANSFORM
cleanedText := LocalAddrCleanLib.CleanPerson73(inputName);
SELF.title := cleanedText[1..5];
SELF.fname := cleanedText[6..25];
SELF.mname := cleanedText[26..45];
SELF.lname := cleanedText[46..65];
SELF.name_suffix := cleanedText[66..70];
SELF.name_score := cleanedText[71..73];
END;
RETURN ROW(createRow);
END;
myRecord t3(myRecord l) := TRANSFORM
SELF.Name := cleanedName2(l.uncleanedName);
SELF := l;
END;
y3 := PROJECT(ds, t3(LEFT));
OUTPUT(y3);
//Example using MODULE structure to return multiple values from a FUNCTION
OperateOnNumbers(Number1, Number2) := FUNCTION
result := MODULE
EXPORT Multiplied := Number1 * Number2;
EXPORT Differenced := Number1 - Number2;
EXPORT Summed := Number1 + Number2;
END;
RETURN result;
END;
OperateOnNumbers(23,22).Multiplied;
OperateOnNumbers(23,22).Differenced;
OperateOnNumbers(23,22).Summed;
See Also: MODULE Structure, TRANSFORM Structure, WHEN