Tuesday, April 20, 2010

FUNCLIB's and Event Scoped Variables

While writing code for my post JSON Encoding in PeopleCode, I discovered a need for transient variable persistence (acknowledged in that post). Since I originally wrote that code in a FUNCLIB, I thought I could reuse/persist my JavaObject variables by moving those two variable declarations above the function declaration. What I found was that this had no impact on the behavior of my code. The FUNCLIB function continued to initialize a new instance of my JavaObject variables on each call. Now, PeopleBooks says that JavaObject variables are treated a little differently than other variables so we should test to see if this behavior exists for regular variables, like String variables. To test this, create a FUNCLIB that contains this code:

Local string &test;

Function testval() Returns string
If (None(&test)) Then
&test = "new value";
Return "Not initialized";
Else
Return "Initialized";
End-If;
End-Function;

You can then test this code with a PSUnit test case defined as follows:

import TTS_UNITTEST:TestBase;

class Test extends TTS_UNITTEST:TestBase
method Test();
method Run();
end-class;

Declare Function testval PeopleCode JJM_SCOPE_FUNC.FUNCLIB FieldFormula;

method Test
%Super = create TTS_UNITTEST:TestBase("Test");
end-method;

method Run
/+ Extends/implements TTS_UNITTEST:TestBase.Run +/
Local number &idx;
For &idx = 1 To 10
%This.Msg(&idx | ": " | testval());
End-For;
end-method;

What does PeopleBooks say about this? What should I expect to see? Summarized, any variable declared within an event is available to all functions within that event (take me to the PeopleBooks reference for this). Given this information, the code does work... as described. The variable is accessible by the FUNCLIB function. PeopleBooks does not say the value will persist after a FUNCLIB function returns. It is important to make this distinction. Event scoped variables are accessible by all functions within an event, but they do not persist after leaving the scope of an event. In other words, once a FUNCLIB returns, the event scoped variables are discarded. Of course, if you call a FUNCLIB function from the same event that defines the FUNCLIB function, then the variable value will persist for the duration of the calling function. But if you did that, then the FUNCLIB function wouldn't really be a FUNCLIB function. It would just be a function. By definition, a FUNCLIB function is a function defined in a different event.

My conclusion: Locally scoped variables are really locally scoped. They don't maintain state when a FUNCLIB function returns. For a FUNCLIB, locally scoped variables are only relevant if you plan to call other functions within the FUNCLIB function's event from the FUNCLIB function.