When working in Legato, it’s very common to come across a task that must be repeated. Several of our example scripts in this blog have used for loops or while loops. In fact, it’s fairly uncommon to write a script without one because almost any task that is complex enough that it would require a script to be written for it generally needs to iterate over something. This week, we’re going to take a look at what makes the two loop types Legato supports different, and why you would choose one over the other.
The for loop:
Example Usage:
for(ix=0 ; ix<5 ; ix++){
AddMessage("test");
}
This is a very basic for loop, just demonstrating a loop that will print out the word "test" 5 times to standard output. The declaration of the loop has 3 parts. First, the counter variable ix is initialized to zero. Then, a semicolon separates the initializer from the conditional statement "ix<5". Once this conditional statement is false, the for loop will end. Generally, this involves our initialized value, but it doesn’t have to. A for loop with a conditional statement of "false<true" is perfectly valid in Legato and will run forever because there is no situation where that statement evaluates to false. Finally, another semicolon separates this conditional from the final part of the loop, the increment. This is where we increase a value in our loop, which should eventually lead to our test condition being false, causing the loop to exit.
Now that we’ve defined the for loop, what kind of jobs would this be best for? Generally, I find it makes the most sense to use a for loop when you are going to loop over a known number of objects. For example, if you’re iterating over a list of files. Anyone reviewing the code can immediately look at the for loop, and if you use conventional variable names like size, it’s pretty easy to tell that the loop is iterating over an array. Look at this loop, for example:
size = ArrayGetAxisDepth(files);
for(ix=0 ; ix<size ; ix++){
AddMessage(files[ix]);
}
Just by looking at the loop declaration and the line above it, a developer can tell that I’m getting the size of the array of files, and then using a for loop to iterate over it to perform a task. It’s very compact and readable code, which is important. It’s always possible to obfuscate code and make it more complicated, but months or years may pass between reviews of a segment of code that has been written, so making it as easy to understand as possible is important.
The while loop:
Example Usage:
ix = 0;
while (ix<5){
AddMessage("test");
ix++;
}
The while loop above is functionally identical to the for loop. Some programmers are more comfortable just using while loops all the time, because anything that can be done with a for loop can be done with a while loop. Instead of having our initializer, our conditional, and our increment on the same line, the while loop is initialized before the loop is entered, and will run while its conditional is true. Within the loop, the value should be incremented at the very end of the loop, if this loop is intended to be run a known number of times. It doesn’t need to be done this way, a while loop doesn’t need to increment every time it runs. It could run multiple times before incrementing the counter variable. The real value of the while loop, though, is in running loops of indeterminate length, that rely on input from a file, or on input from a user. Take the following code snippet for example:
int rc;
rc = IDYES;
while(rc == IDYES){
AddMessage("test");
rc = YesNoBox("Print another message?");
}
This simple loop initializes our variable rc to the defined value IDYES, and our conditional statement in the while loop will run as long as the the value of rc is equal to IDYES. There is no incremented value in this loop; instead the conditional for the while loop only becomes false if the user input sets the value to anything other than IDYES. This allows us to have a loop that does not have a known duration, which will instead just run until the program encounters a value that causes its conditional test statement to fail.
It’s not particularly clean, but that statement can also be written as a for loop, like the example below:
int rc;
for(rc=IDYES ; rc==IDYES ; rc){
AddMessage("test");
rc = YesNoBox("Print another message?");
}
Our while loop doesn’t have an incremented value, but a for loop must have an integer value in that position. It’s required by the syntax of the language. To get around that then, we can simply put the variable rc in the expected position for the incremented value. If we don’t have a ++ operator after it, the value isn’t incremented, it’s just there to fill up the required space by the loop syntax. The loop itself is a bit less clear on what it’s actually doing. Most programmers would find the purpose of the while loop to be significantly easier to understand because using a for loop like this clunky. Another advantage of while loops in Legato is the ability to put functions in the conditional statement.
In the end, either loop can be used in place of the other. When it comes down to it, most programmers tend to use for loops to run a known number of times (for example, to iterate over all characters in a string or all files in a folder). When a programmer encounters a task that requires a function to loop a non-known number of times (for example scanning a file until a key word is found or until a user interrupts the application), a while loop makes the most sense to use.
Steven Horowitz has been working for Novaworks for over five years as a technical expert with a focus on EDGAR HTML and XBRL. Since the creation of the Legato language in 2015, Steven has been developing scripts to improve the GoFiler user experience. He is currently working toward a Bachelor of Sciences in Software Engineering at RIT and MCC. |
Additional Resources
Novaworks’ Legato Resources
Legato Script Developers LinkedIn Group
Primer: An Introduction to Legato