Level: Advanced, Version: FM 16 or later

Set Variable By Name Revisited

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].

INTRODUCTION

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…

  1. Dynamic Variable Instantiation (written way back in 2011), which suggested creating variables on the fly via Evaluate + Let, e.g.,
  2. 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.

DIGGING DEEPER

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…

“pi” is rejected because it is a function name

…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.

  1. 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
  2. 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.

  1. Get Var –
    • determines whether the corresponding var name is standard or hexadecimal
    • displays the contents of that var
  2. 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.

5 thoughts on “Set Variable By Name Revisited”

  1. For most of the examples, when naming variables, why not just use literals for the symbols and leave out the spaces? Ex: $$PlusPi, $ProfitAndLoss, $LessThanThis. And for a reserved word, just add another word, such as “This”. Ex: $ThisLayout. What does $+Pi mean anyway? I find literal names typically more readable.

    I get that you might want to use a readable window name for a variable name (as in the original 2011 example). But since you know what you are naming the windows, you can create a CF to substitute() any symbols, and a corresponding undo CF
    Ex: “This – Window Name” => $ThisDashWindowName

    At least that feels better than having hex-named variables.

    1. Hi Richard,

      Thanks for taking the time to comment… if you are manually assigning the var names, then sure, make them whatever you like. I may not have made this sufficiently clear in the article, but my goal is to have a system that can automatically roll with whatever name is handed to it.

      Kevin

      1. Got it. So a user might be specifying the name, or a script from another interface. Good point. You could still just create a CF that would deal with the truly forbidden characters and words. Could be just a series of substitutions. Just trying to avoid the idea of hex names.

        But I guess since they are produced programmatically, it does not really matter (except that debugging is a bit more complicated).

    1. Thank you Peter. The CF has been repaired, and the demo has been updated to v3. Really appreciate you pointing that out!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.