Setting multiple variables at once, several ways

In many of my macros I set several local variables to zero at the start of the macro. I never thought to ask myself if I can set several variables at the same time in the same action. I even asked ChatGPT but it said "no" (but it did show how to do it with multiple macOS "osascript commands" or multiple AppleScripts's "set variable", which I think is too much work to be useful.) It also showed a way to do it if the variables shared the same prefix, like the string "Local":

The above action will set two variables, called "LocalWidth" and "LocalHeight". Since many variables begin with the word "Local" or "Instance", that approach could help me out in a few cases. But all those quotation marks don't make it easy to type.

I also found an old post in which The Architect explains how it could be done in another special case: (when the variables end with sequential numbers)

The above approach could also help me out in a few cases.

But today I found a way to do it, which proves ChatGPT can be wrong. Here's my method:

That will assign several variables with any set of names to four separate values. Best of all, you get to see the assignment values in the macro, and you don't have to use quotes.

I suspect that many people will still consider this too much work to assign a small number of variables, but I like it anyway.

I did some speed tests, and found that the Search Text action costs exactly as much time as two Set Variable actions, regardless of how many variables you set in the Search Text action. As a result, it's actually faster to use this action if you have more than two variables to set. So if speed matters to you, this is the faster approach.

Don't forget, the Text Box can contain tokens, including tokens that can return different results, like %Calculate%%. Oddly enough, this action doesn't contain any flags to disable token processing. I would suggest that this is a feature omission.

3 Likes

Very creative! Now if we could just delete them all just as easily, without resorting to AppleScript solutions :).

-rob.

Multiple variables

Why ?

Without context, this feels a bit like an XY problem.

If you need a large number of named values to solve some (as yet unidentified :slight_smile: ) problem, you could just use a single JSON key-value object, with as many keys as you like, and the %JSONValue% as a direct and built-in way of reading particular values from it.

2 Likes

Perhaps you didn't notice that I already described the JSON solution in my post, and I also identified its limitations.

My post doesn't have problems, only solutions. You must be a glass half empty person.

2 Likes

Or you can just use the plug in I created in response to another user's request. It can be found here:

2 Likes

That's stunning.

Thanks @Airy - it's not something I've ever used myself but it seemed relevant to your topic :grinning:

1 Like

I think @ComplexPoint is suggesting you don't resolve the JSON to individual variables -- keep the blob, but reference what you need as you need it. That would have advantages in some situations, but I think it's a solution to a different problem.

I do like your "Search" approach for a known number of values with known contents (so you can pick the right "split" character(s)).

I'll disagree here, though. That option is all-or-nothing for the action and the choice hidden -- better, IMO, to escape the tokens you don't want processed so you've flexibility and visibility. I doubt that many people will want so many unprocessed tokens here that the extra %s would be an issue!

(And, from a quick skim, processing options are only available for actions with a single text field -- so its inclusion here could mean a major, low-level, re-write!).

This is a task I've enjoyed pondering on myself, and I really do enjoy your approaches here @Airy as well!

I've posted my takes on the task in the thread Feature Request: Set Values for "Multiple" Variables in "One" Action, where you can also find some other approaches.

Setting up multiple variables to different tokens or values could for instance be set up as neatly as this:

Whereas setting them all to same value could be set up even simpler, like this (this same value could for instance be tokens like %Delete% or values like 0, as it would for many use cases):

This method is mostly thought out for tidiness, readability and ease of use, but it is also way fast enough for most all real world use cases (from my measurements adding only about ~12ms, total, to the ~2ms it takes for each Set Variable to Text action).

3 Likes

Aha ! A solution in search of a problem.

I think :thinking: I’ve heard of those.

Like the Calvin and Hobbes transmogrifier ?

1 Like

Both. :slight_smile:

Well it is Christmas. I don't see it as an example of the "XY problem" but as an interesting technique. However, I wouldn't use it in this particular context because of wanting things to be clear, intuitive and boring.

That said, perhaps I have not yet imagined a case in which it would be a superior approach.

So it seems to me for this context, but interesting nonetheless.

1 Like

Of course, actions can always be renamed, or (in the case of example 1) be put in a renamed Group. That's just a little more effort.

Who is up for an Obfuscated Keyboard Maestro Macro Contest in the new year? :laughing:

2 Likes

That's clever referencing different parts of the variable in this context! It took me a second to recognize since you are using ➣ as a separator instead of a comma :+1:

In case it's helpful for anyone, this is the same thing using the default separator:

So each local__line variable is separated by the comma, and then each part of the variable is referenced by %Variable%local__line[1]%, %Variable%local__line[2]%

%Variable%local__line[1]% → "local__A"
%Variable%local__line[2]% → "This is the value of the variable local__A"

1 Like

True, it obscured the technique at hand, and thank you for demonstrating it more clearly using the comma!

The use of ➣, or another custom delimiter, is for more than only style or readability though — The delimiter needs to be set to something not (likely) appearing in any value you'd want to set.

Example, using this technique and comma as a delimiter: Trying to set the value to "text before comma, followed by more text you'd also like to set your variable value to", would then only result in the variable being set to "text before comma"

Gotcha. I tend to use the section sign § when I want to avoid misfiring, but I don't know that I've ever had a use case like this. Your format makes sense because it's both unique and readable. Nice!

1 Like

The reason your "boring old way" looks shorter than my new way is because you compressed all four actions in your boring old way while you didn't compress my way. I know what you're going to say, "But I can see all the assignments with compressed actions." Well, you can also do that with my solution, like this:

Now my solution is over four times shorter than yours (and still twice as fast). Here's how it expands:

Thanks. Naturally, I know my ideas aren't always the best, but it's nice to get a little recognition once in a while. So, thanks.

Yes I did: see the red macro.

But I can see all the assignments with compressed actions. (Dang! How does he do it?).

As in the red macro, yep. My point there was that:

"Search Text "a=100,b=100,c=8,d=abc" Using Regular Expression (ignoring case)"

is not as clear as:

Set Variable "local a" To Calculation "100"
Set Variable "local b" To Calculation "100"
Set Variable "local c" To Calculation "99"
Set Variable "local d" to Text "abc"

The highlighting is Markdown's not mine. Yes, even Markdown knows what's going on there! :wink:

Yes, it's better if that is the aim and one doesn't want the extra work of using (as I mentioned) a Group action.

I like that version better as it is much less opaque. Even so,

Search Text "a=100,b=100,c=8,d=abc" Using Regular Expression (ignoring case)

doesn't inherently mean the same as:

Set Variable "local a" To Calculation "100"
Set Variable "local b" To Calculation "100"
Set Variable "local c" To Calculation "99"
Set Variable "local d" to Text "abc"

Here's my own macro with the same automatically generated title:

Expanded:

Of course, your macros won't be opaque to you, so it's not, of course, a question of your method being right or wrong if it suits you. For a macro made available to others however, readability becomes a higher priority. I like mundane actions to be "boring" for myself too, to avoid having to think about them.

Yes, I was interested by what you had said about this being faster when it is run. One of the reasons your approach is worth noting is for use in situations where speed of execution is a high priority.

Your idea is interesting, as I said. I can imagine using a similar technique for some things, although probably not for assigning variables, and certainly not as my default way of assigning variables, for the reasons I have given. It's just a question of priorities or preferences.