This is a stripped-down version of a single section of Grok TiddlyWiki, optimized for fast loading and readability by search engines. Some features are missing.

## Using Variables in Macros

10th April 2021 at 8:55am

In many cases, macros get all the information they need to vary their output from their parameters. But it's also possible for them to get information from the values of variables where the macro is called.

First of all, there's the obvious way, by simply using an ordinary variable transclusion:

\define findX()
The current value of X is "<<X>>".
\end

<$set name=X value="marks the spot"> <<findX>> </$set>

The current value of X is "marks the spot".

However, as we just saw in the previous section, variable transclusions only work in a limited range of situations; sometimes we need Text Substitution to accomplish the goal of our macro. The syntax for performing text substitution on a variable is $(variable)$ – that is, add parentheses immediately inside the dollar signs that indicate the text substitution of a parameter. (Note that this only works within a macro – you can't do text substitution of any kind outside a macro.)

Let's look at our good old getPhone example again and make it work without parameters.

\define getPhone()
{{$(person)$!!phone}}
\end

<$set name=person value={{!!manager}}> <<getPhone>> </$set>

Nothing tricky here beyond remembering the syntax. But why would we want to do this? Generally, if we have the choice, we don't; it's clearer what information the macro is using when we use parameters, and it's not a good thing when macros do something surprising. (See the Principle of Least Astonishment.)

However, there are some situations where text substitution on a variable can allow us to do something we couldn't do otherwise. Let's think back to the situation in Filters and Transclusions where we tried unsuccessfully to use a macro rather than including field transclusions in a filter. What we were trying to do was essentially this, if only it were valid syntax:

\define myfilt(people)
[enlist[$people$]]
\end

<$list filter=<<myfilt {{!!family}}>> /> Our attempts to fix this by changing the myfilt macro call to a $macrocall widget or by adding a variable were also unsuccessful, because we seemingly needed the also-invalid syntax:

<$set name=myvalue value=<$macrocall $name="myfilt" people={{!!family}}/>> With the ability to do variable text substitutions, now we can do it like this: \define myfilt() [enlist[$(people)$]] \end <$set name=people value={{!!family}}>
<$list filter=<<myfilt>> /> </$set>

This isn't quite as clean as just transcluding the fields directly into the filter as we learned how to do in Filters and Transclusions – and if the list of people contains weird characters we could land ourselves in trouble since we're using text substitution – but it's much better than some of the stuff we were trying to do before!

You will find this pattern quite helpful when dealing with multiple layers of macros and widgets.

## Exercises

Suppose we want to create a link for a contact which, when clicked on a smartphone, calls the contact. This can be accomplished with a link to a URL like tel:888-555-1234. Create such a link and add it to the ContactInformationTemplate.

If you want to use a [[double square brackets]] link rather than an a HTML element, you need to use ext, like this:

[ext[tel:888-555-1234]]

That's because tel:888-555-1234 by itself would be a valid name for a tiddler, too, so if TiddlyWiki isn't told it's an external link, it will assume it's an internal one. See the External Links heading here in the TiddlyWiki documentation for more information.

Repeat the previous exercise, but this time use a filter rather than a macro to combine the tel: part and the phone number. You may need to visit the TiddlyWiki documentation to find an appropriate filter operator.