Today we’re going to dig a little deeper into the new-in-18 While function, and to avoid repetition, will assume readers are familiar with last month’s article on SetRecursion and While. We’ll look at some new examples ranging from basic to advanced, investigate the circumstances under which While can use variables previously declared via Let, and check out some benchmark results comparing While vs. CustomList.
Annotated Example: List of Counting Numbers
While ( [ initVar ] ; condition ; [ logic ] ; result )
Here’s a very simple example. It doesn’t do much, just displays a list of numbers.
This function was originally going to be named “Loop”, and that would have been a good name, since the function loops internally, applying [logic] over and over, until the exit condition is met. Having said that, I’m glad the function name was changed, a) to avoid confusion with the Loop script step, and b) because While is an accurate name, in the sense of “as long as condition is true, keep applying [logic]; when condition is no longer true, display the result.”
Reversing A Text String
- use Middle() to “walk” the text string (a) from right to left, extract one character at a time, and assemble a new string from left to right
- the b var starts out containing the string length; with each iteration, de-increment the b var by 1
- display the result when b = 0
Under what circumstances are variables previously declared via Let visible to and/or transformable by While? Bearing mind the unusual structure of the function…
While ( [ initVar ] ; condition ; [ logic ] ; result )
It turns out that a) all vars previously declared by Let are visible, but b) any var that is transformed in the [logic] section “must” be declared in the [initVar] section. I put “must” in quotes because there’s an exception which I’ll get to in a moment.
This works (because the “a” var isn’t transformed in the [logic] section):
But move “b” or “x” up into the Let declaration and it breaks:
Here’s the exception I alluded to above — we can use local ($) or global ($$) vars rather than standard Let vars… and note that since $x starts out empty, we can transform it in the [logic] section w/o having pre-declared it.
Other points of interest:
- Under these circumstances it’s okay to leave the [initVar] section empty
- When you instantiate $vars or $$vars within a calculation, you should manually clean them up at the end, as per the second Let declaration above.
Note: you can leave While’s [initVar] declaration empty, but if you put “” in there it breaks (returns an empty result).
Okay, let’s look at some more regular (non-$var) examples.
While within While
Here the outer While builds a vertical list, and the inner While builds a horizontal comma-delimited list.
Typically, I find While easier to work with than CustomList, but in this particular instance, CustomList is a clear winner in terms of ease-of-implementation:
Lost in Austen
Returning to the Jane Austen text (the first chapter of Pride And Prejudice) we played with last time…
This time around we have two examples. First an alphabetically-arranged index, showing how many times each word occurs in the chapter.
Explanation: Generate the alphabetical index using SortValues and UniqueValues — no need for While to do that. Where While comes in handy is to count the occurrences of each word, and then append that information. Use FilterValues rather than PatternCount to avoid false positives (we only want to count “a” when it’s a standalone word, not when it occurs inside other words).
Next up, this comes from a real-world need someone posted to one of the online forums. How to identify the longest word in each paragraph… and one of the fun parts of this challenge is that multiple words may be tied for that honor.
As we saw in the earlier While-invoking-While example, here we have the outer While generating the vertical list, and the inner While processing each paragraph to extract the longest word(s).
We last looked at Pascal’s Triangle back in 2011 in this two-part series: Combinations and Pascal’s Triangle, part 1 and Combinations and Pascal’s Triangle, part 2, and the following discussion will assume that the reader is either somewhat familiar with Pascal’s Triangle or has read part 1 of the aforementioned series.
Note: this is a separate demo file, and not part of the main “Sandbox v2” demo.
Once again, we have nested While functions, and once again the outer While is responsible for generating the vertical component and the inner While for the horizontal.
In situations like this I find it helpful to first solve the “inner problem” (or some sub-component thereof), and worry about the big picture later. Specifically here, assembling a row involves summing value pairs from the preceding row, so I worked things out in the data viewer and produced row 5, using row 4 (“1 3 3 1”) as a test case.
FM 18 Runtime Merge Code
Our final demo today comes from a presentation I gave at PauseOnError in 2014. At the time I used a custom function; here the approach has been updated to use While instead. This bare-bones demo shows a minimal implementation of a potentially powerful technique.
There is a Templates table…
…and an Aliases table where the Input field contains faux merge fields and the Output field contains runtime code.
When the user chooses a template…
…this triggered script step translates the Input into the Output…
…with something along the lines of this as a result.
Note: for debugging purposes, if you hold down the Ctrl key during letter generation, you will see the merge data in red.
And that brings us to the end of today’s demos.
Preliminary Benchmarking While vs. CustomList
All tests conducted on my elderly Win 7 laptop. Preliminary results suggest that which function is faster comes down to the kind of task you’re performing…
TASK 1 — if the task involves building a large list, then CustomList is faster, e.g., assembling a space-delimited list of the numbers 1 – n takes both While and CustomList approximately 4 seconds when n = 70K… but increase n to 90K and While takes 9 seconds, but CustomList only takes 5 seconds.
TASK 1: While
TASK 1: CustomList
TASK 2 — bear in mind that CustomList always produces a return-delimited list… you are welcome to transform it as you please but you do incur the overhead of building the list… this test simply iterates a counter from 1 to 300K and displays the result, which While can do in 2 seconds, whereas CustomList takes 14 seconds.
TASK 2: While
TASK 2: CustomList
TASK 3 — add .0001 to itself 100K times. While takes 1 second; CustomList takes 5 seconds. But of course CustomList isn’t just doing the math… it’s also generating a list containing 100K values.
TASK 3: While
TASK 3: CustomList
I can’t think of a better way to end than with a modified version of the conclusion from my CustomList article. My goal today, and in last month’s article, has been to convey some sense of the breadth and depth of what can be accomplished via While. The particulars of my examples aren’t nearly as important as the general idea that this is a powerful and flexible tool worth having in your FileMaker tool box. If you’ve solved an interesting problem using While, I encourage you to post a comment here, explaining what the problem was and how you solved it.