Variable scope is a key concept in Claris FileMaker. This article will explain the differences between the three variable scopes and introduce some common use cases for each. Also, did you know FileMaker secretly introduced a fourth scope type with the introduction of the While () function?
Once upon a time, when things were simpler, there were three different variable scopes: global, local and function.
It might be easier to show the relationship between different variable scopes using the image below. Global variables operate at the file level, local variables operate at the script level, and function variables operate at the function level.
A simple representation of the three variable levels
At the highest level, we have global variables. Global variables operate at the file level. They can be identified by the double dollar sign ($$) in front of the variable name. Once a global variable is created in a file, it will live on until the file is closed or it is manually cleared out. It can be read and written in any scripts or calculations that reside in the same file while it’s alive.
Global variables can be accessed across the whole file. They are commonly used to store system-level metadata, such as application version and user account name.
Example of global variables storing system-level metadata
If we look at this image, I set a global variable upon the first window open to display the subject of the demo. If we create a second or third layout, we can insert the same global variable onto the layout to show the same subject across the system.
When we need to create another file with a different subject, all we need to do is modify the script to set the global variable to a different value without having to modify all layouts. See the image below as an example.
Using the global variable for display across multiple layouts
Starting with FileMaker 16, we can even use global variables to specify external data sources, as described in this article.
Drawbacks of using Global Variables
Global variables seem convenient because we can define them once and use them everywhere. However, due to this characteristic, global variables also require a lot of maintenance. Suppose we use global variables in one part of our solution. It’s very common to get an unexpected result because we forgot that the same variable can be set in a different part of our solution.
Personally, I’d suggest using global variables to store values that don’t change much during a user session. If we need to use global variables to store values that frequently change, it’s a good practice to clear out our global variables after we’re done.
Because of the maintenance required, I don’t recommend using global variables to pass data between scripts. Now that we have script parameters and JSON functions, these are better suited for passing data.
Local variables are located one level below global variables. They are identified by a single dollar sign ($) in front of their variable names. Local variables operate at the script level. Once a local variable is created in a script, it will live on until the script ends or is manually cleared out. It can be read or written in any script steps or calculations in the same script while it’s alive.
Compared to the global variables, local variables get automatically cleared out when a script ends, and therefore require less maintenance than global variables.
The most common usage for local variables is as temporary storage space within a script. However, they can actually do much more than this. For example, we can access local variables outside of our script from our layout or even the security setting.
One thing to note is that local variables defined in one script are not accessible from its subscripts. Each script has its own scope.
The picture below is a more accurate representation of scope of local variables.
As mentioned earlier, if we do want to pass values between scripts, use the script parameter feature.
Function variables have no prefixes. Personally, I add an underscore in front of function variables to differentiate them from actual function names.
Function variables within a While () function
Scope of Function Variables
The scope of function variables is a bit complicated, because their scopes can be nested. Before FileMaker 18, the only native FileMaker function that allowed us to set variables was the Let () function. If we nest multiple Let () functions together, the outer ones are considered to have a larger scope than the inner ones.
Function variables that are defined in larger scopes can be read from smaller scopes. Notice that this is slightly different from the global or local variables. Those two can be both read and written within smaller scopes. But function variables can only be read but not written within smaller scopes.
This means if we name a variable in a smaller scope function the same name as a variable in a larger scope function, they are independent.
We’ll look at the formula in the image below as an example. There are two Let () functions nested together. The outer one has a larger scope and the inner one has a smaller scope. Pay attention to the row “_var3 = _var3 + 1“. The _var3 before the equal sign is a function variable defined within the scope of the inner Let () function while the _var3 after the equal sign is inherited from the outer Let () function. As two function variables, they are independent. This is why at the final output _var3 is equal to 3 instead of 4, because whatever happened in the inner Let () function doesn’t concern the _var3 in the outer Let () function.
Larger scope variable _var 3 is readable but not modifiable from the smaller scope
The Fourth (Hidden!) Variable Scope
Fast forward to now, with the While () function introduced in FileMaker 18, which introduced a fourth hidden scope. It doesn’t have a name, but I call it the loop scope. If you are not familiar with the While () function, check out this video.
We know that a While () function has four parameters: initialVariable, condition, logic, and return.
Similar behavior between the While () Function and the Let () Function
If we compare a While () function to a Let () function, we will realize they are actually very similar. In fact, a While () function can collapse into a Let () function, if we set the condition parameter to 0 and the logic parameter to empty. For example, the two functions shown in the images below behave the same:
This While () function collapse into a Let () function
In a While () function, we can declare function variables in the first parameter (the initialVariable parameter), then reference them in later parameters. Any nested Let () or While () functions within the first or the last parameter follows the same rule that we talked about when nesting Let () functions.
The logic parameter of the While () function behaves differently
The second parameter of a While () function, the condition parameter, doesn’t allow us to set variables directly. So what’s really new here, is the third parameter, the logic parameter.
In the Logic parameter, we are allowed to set variables. These could be global, local or function variables. For global and local variables, they behave as expected, meaning if we set their values, the changes are visible within their corresponding scope. If we update a global here, that change can be seen in the whole file. If we update a local variable, that change can be seen later in the script.
What if we set a function variable in the logic parameter? Does the change persist throughout the entire While () function? It depends. It depends on whether this variable has been declared in the first parameter of this While () function. If so, the changes we made will be accessible throughout the entire While () function. If the function variable is declared only within the logic parameter, it gets cleared out after a single loop.
We have spent a lot of time talking about variable scope. One important thing to define the scope of a variable is the variable’s lifespan: global variables live and die with the file. When a file is closed, the globals get cleared. Local variables live and die with a script. When the script ends, they get cleared.
By that logic, function variables should live and die with a function. But clearly, with the While () function, some variables get cleared sooner and more frequently than others. This tells us there is a hidden fourth scope within the While () function’s logic parameter. Variables declared in this scope live and die with a loop. When the loop ends, they get cleared out.
The Loop Scope
So by the same naming logic, we should call this the loop scope. At this moment, the loop scope only exists within a While () function and behaves like a smaller scope to the While () function that contains it.
Within the loop, we have both read and write access to variables declared in its parent While () function and read-only access to variables declared in larger scopes.
So if we take the While () function into consideration, a more accurate representation of different scopes should be like this:
A more accurate representation takes the “loop scope” into consideration
Confused yet? You might be wondering, why should I care about functional variables when I already have global and local variables to work with?
The calculation engine is a powerful tool that FileMaker offers to handle business logic. Being able to work with Let () or While () functions will unlock the full power of the calculation engine. In order to work with the Let () and While () functions, we need to know how to work with function variables.
If you’d like to learn more from us, check out our training classes.
*This article was originally written for AppWorks, which has since joined Direct Impact Solutions. This article is intended for informative purposes only. To the best of our knowledge, this information is accurate as of the date of publication.