Demo file: set-variable-by-name-v3.zip (requires FM 16 or later)
[Demo has been upgraded to v3 to fix a bug in the cfZap custom function].
You’ve probably heard the old joke that goes…
Patient: Doc, it hurts when I do this.
Doctor: Don’t do that.
Perhaps you’re also familiar with the FileMaker equivalent?
Developer: It hurts when I try to assign certain variable names.
FileMaker: Don’t do that.
Or how about this one?
Developer: I need to assign variable names programmatically.
FileMaker: Don’t do that.
We’ve touched on this and related issues several times in the past, including…
- Dynamic Variable Instantiation (written way back in 2011), which suggested creating variables on the fly via Evaluate + Let, e.g.,
- Set Variable By Name (from 2016), which introduced a custom function to streamline the preceding
…and today we have an updated version (two versions, actually) of the SetVarByName custom function.
In case you’re wondering why you might want to set variables by name, we saw one use case a few years back in Virtual List Reporting, part 3, where the challenge was to produce multiple independent reports concurrently, each in its own browse mode window, based on a single layout, with the underlying variables for each report scoped to that report’s window name.
Did you notice in the above image that I avoided a don’t do that moment re: my attempt to use window names containing hyphens as the basis for variable names?
Reminder: a variable name is invalid (cannot be defined) if, among other things, it…
…and I dodged the issue by substituting n-dashes for hyphens, but clearly it would be preferable to be able to a) define a variable, and b) subsequently retrieve data from that variable, without having to worry about the legality of the name.
So we have this list of prohibited items…
…but it turns out that, while none of them are permitted by Set Variable…
…only the items boxed in red are actually forbidden if you instantiate the variable via Let.
[Or so testing conducted thus far would seem to indicate.]
So there’s nothing stopping us from declaring a $$pi variable via Let…
…and sure enough we can see it in the Data Viewer…
…and reference it like any other variable, despite the supposed illegality of its name.
But if we want to include any of the truly forbidden characters, which is to say, any of these…
…we’ll need to employ some sort of workaround beyond merely invoking Let, because they actually are prohibited, for example:
ABOUT THE DEMO
The two “Set Var” buttons invoke their respective CFs via script.
- Set Var – defines a variable based on Type, Name and Repetition
- Renders “name” directly if possible, otherwise encodes it as hexadecimal
- Flexibly interprets “contents” as run-time code if possible; otherwise literally
- Accomodates any legal rep number, including zero and negative values
- Set Var Literal – works the same as Set Var, but always renders “contents” literally
For testing purposes the “Get Var” and “Clear Var” buttons are single-action, enabling them to work as expected with both $$vars and $vars.
- Get Var –
- determines whether the corresponding var name is standard or hexadecimal
- displays the contents of that var
- Clear Var – invokes SetVarByName with “” as the argument
Note: to test buttons 3 and 4 with $vars, set the Type to $ and invoke buttons 1 or 2 with the debugger on.
QUESTIONS & ANSWERS
Q. What’s the difference between Set Var and Set Var Literal?
A. It has to do with how contents are interpreted. For example, clicking Set Var here…
…returns this in the Data Viewer (since the layout name is “demo”)…
…but if you click Set Var Literal, you will instead see…
Q. What does a hex-encoded variable look like?
A. Let’s find out. Click Set Var here…
…and, since the word “and” cannot be part of a variable name, the hexadecimal equivalent of the variable name will be declared instead…
…and, as mentioned earlier, Get Var is smart enough to figure this out.
Q. I just took a look at the CF definitions, and also the Get Var logic — why didn’t you use the EvaluationError function to determine whether or not to hex encode variable names?
A. I wanted to, but it turns out that you can’t always trust it. For example, we know that a “+” in a variable name is a deal breaker, but EvaluationError doesn’t have a problem with $$+Pi (I’m guessing because it sees it as $$3.14159…).
Nevertheless you cannot create a variable named $$+Pi, either via Set Variable or via Let (the confirmation or refutation of this assertion will be left as an exercise for the reader).
Q. Why not simply HexEncode all dynamic variable names?
A. Good question. I’d say that’s a judgement call. Personally, I like the idea of human-readable var names during the development and debugging cycles. On the other hand, there’s additional overhead associated with maintaining two approaches and if it came down to gaining better performance I’d gladly sacrifice readable var names.
Q. Anything else you’d like to add?
A. Just that like many of the techniques featured on this site, this is a work in progress, and I encourage people to experiment with the demo and let me know if I’ve overlooked anything or if they discover anything interesting.