In the Loop

Nuair-a loops

In the previous section we learned about le idir loops. They were very useful for repeating pieces of code, but we needed to know how many times we wanted to loop before it started. What if we don’t know how many times we need to loop? Or what if we want to loop forever? This is where “nuair-a” loops come in.

“nuair a” translates roughly as “when” or “while”. We use the `nuair-a` keyword to denote a new type of loop.

“le idir” loops were defined by providing a start and a stop value, `nuair-a` loops are instead defined by providing a condition that can be checked every time the loop loops.

The syntax for a `nuair-a` loop is:

``````nuair-a < condition > {
<code to be repeated>
}``````

The way a nuair-a loop works is:

1. When Setanta reaches a `nuair-a` loop, it first checks if the condition is true, like how a `má` statement would. If the condition is false it exits the loop and continues on afterwards. If the condition is true, then it moves to step 2.
2. Step 2 is execute the code between the curly braces `{ }`.
3. After executing the code, the Setanta interpreter returns to step 1.

Here’s a quick example:

Example

Running that code we can see that it writes “0”, then “1”, then “2”. Why?

• The first line creates a new variable `x` and starts it with value 0.
• Next we create a new `nuair-a` loop with the condition `x < 3`.
• Setanta checks this condition, is `x` less than 3? Well `x` is currently 0, so yes.
• The check was successful so Setanta executes the code inside the braces. It first writes `x` (currently 0), then increases `x` by 1. (Using the short-hand “`x += 1`” for “`x = x + 1`).
• Now `x` is equal to 1.
• Setanta now returns to the condition, is `x` still less than 3? Yes. So we once again execute the code inside the braces. Causing “1” to be written on the console and `x` to be increased to 2.
• This happens once again now that `x` is equal to 2. This is still less than 3 so we write “2” and increase `x` to 3.
• This time when Setanta checks the condition `x < 3` it finds that it’s false, as now `x` is 3. This means we are finished with the loop and the program is over.

Looping forever!

What if we want to run a loop forever? For example a program that prints “Hello”, waits 2 seconds, prints “Hello”, waits 2 seconds, prints “Hello” etc etc. We can do this by specifying some condition that will never be false.

We could write something that’s always true like `1 == 1` or `10 + 20 == 30`, but the easiest thing to do is just use the boolean `fíor`, which just means “true”. It’s the most true thing we can have!

This means we can write a loop that never ends by writing:

``````nuair-a fíor {
}``````

Let’s try out our program to print “Hello” and sleep for 2 seconds.

Before we start, I should point out that when Setanta code is running in the editor the button becomes a button. Clicking will stop the program. We’ll need this to stop our infinite loop (We’ll see another way of stopping loops soon).

Ok, back to our program. Let’s fill in `scríobh("Hello")` and `coladh(2000)` between the curly braces to have it be executed forever. Try it out!

Nesting

Loops can contain any code you like, including other loops! These are known as nested loops.

Each time the outer loop does one loop, the inner loop will run until it’s finished. This can be used to get some complicated behaviour.

Example

Let’s look at the simplest example of nested loops, one loop inside the other:

Both of these loops start at 0 and run up to 3. Each iteration of the inner loop prints out the current value of `i`, the outer loop variable, and `j`, the inner loop variable.

If you run the code you will see that the inner loop goes through each of it’s values (0, 1, and 2) for each value of the outer loop.

Colour cycle

This technique can be used for many things. For example, say we have a list of colours, and a list of sizes, we can draw a circle of each colour, and each size by using nested loops.

Let’s start with our list of colours and one le idir loop to loop through the colours:

``````colours := ["glas", "buí", "bándearg", "gorm"]

>-- Outer loop loops through the colours
le i idir (0, fad@colours) {
colour := colours[i]

>-- Change colour
dath@stáitse(colour)
}``````

Now we can add our list of sizes, let’s use 3 sizes, 50, 100 and 200. We put in an inner loop that loops through the sizes.

``````colours := ["glas", "buí", "bándearg", "gorm"]

sizes := [50, 100, 200]

>-- Outer loop loops through the colours
le i idir (0, fad@colours) {
colour := colours[i]

>-- Change colour
dath@stáitse(colour)

>-- Inner loop loops through the sizes
le j idir (0, fad@sizes) {
size := sizes[j]
}
}``````

We are careful here to use different names for the loop variables (`i` and `j`) so that we can refer to them at the same time.

Now inside the inner loop we have access to a size and a colour. Let’s use the `glan@stáitse` action the clear the stage (“glan” translates as “clean”), then draw a circle of that size.

Where do we draw the circle? Let’s use `fad_x@stáitse` and `fad_y@stáitse` to get the mid-point of the stage. To find the middle we should divide by 2.

``````colours := ["glas", "buí", "bándearg", "gorm"]

sizes := [50, 100, 200]

>-- Outer loop loops through the colours
le i idir (0, fad@colours) {
colour := colours[i]

>-- Change colour
dath@stáitse(colour)

>-- Inner loop loops through the sizes
le j idir (0, fad@sizes) {
size := sizes[j]

>-- Clear the stage
glan@stáitse()

>-- Draw the circle at the midpoint with radius `size`
}
}``````

The final step we should take is to wait (sleep) for a short time before moving on to the next circle. This is just to leave the circles on the screen long enough for us to see them. We just add a call to `coladh` to the inner loop, after we draw the circle.

Let’s try it out:

Stop!

Let’s say we want to write a program that will let the user type in a list of text until they say “stop”, then we’ll print the list back to them.

We can use the `léigh` action (meaning “read”) to read user input. Let’s start out with a `nuair-a fíor` loop. We’ll see how to exit the loop later.

``````>-- Create an empty list
list := []

>-- Loop forever
nuair-a fíor {
>-- Read from the console with léigh
text := léigh()

>-- Add `text` to the end of the list
list += [text]
}``````

This program will forever keep asking the user for input, then add that input into the `list`.

We’d like to exit the loop when the user says “Stop”, how do we do that?

DIY

One way we can do it is by using a condition in our `nuair-a` loop. We’ll make a new variable called `keep_going`, that starts out equal to `fíor` (“true”). We’ll use this variable as the condition.

``````>-- Create an empty list
list := []

keep_going := fíor

nuair-a keep_going {
>-- Read from the console with léigh
text := léigh()

>-- Add `text` to the end of the list
list += [text]
}``````

This program will keep looping while `keep_going` is `fíor`. Therefore we can stop the loop by changing the value of `keep_going` when the user inputs “Stop”.

Let’s use a `má` statement to check if they’ve said “Stop”.

``````>-- Create an empty list
list := []

keep_going := fíor

nuair-a keep_going {
>-- Read from the console with léigh
text := léigh()

má text == "Stop" {
>-- They said "Stop"
} nó {
>-- They didn't say "Stop".

>-- Add `text` to the end of the list
list += [text]
}
}``````

Now we can tell Setanta to change `keep_going` to `bréag` (“false”) when they say “Stop” by adding `keep_going = bréag` inside the `má` statement.

``````>-- Create an empty list
list := []

keep_going := fíor

nuair-a keep_going {
>-- Read from the console with léigh
text := léigh()

má text == "Stop" {
>-- They said "Stop"
keep_going = bréag
} nó {
>-- They didn't say "Stop".

>-- Add `text` to the end of the list
list += [text]
}
}``````

Now let’s add a line to write the list after the loop is finished, (`scríobh(list)`).

You can try out the program and see that it works: Run the program and enter a few words into the console, then enter “Stop” and you’ll see that the program stops and prints the list.

Here’s a GIF of it in action:

A Better Way

That code worked, but it was very messy! Surely there’s an easier way. Lucky for us, there is. Setanta includes a special keyword called “`bris`”. “Bris” translates as “Break”, and it allows us to break out of a loop.

When Setanta reads the `bris` keyword inside a loop it stops what it’s doing, and leaves the loop immediately.

Try it out here:

Running this code we see that it writes “0”, “1”, “2”, “3” and “4”. Why does it stop at 4? The outer loop goes from 0 to 10.

The secret lies in the `má` statement on line 3. It checks if `i` is equal to 5, and if it is it executes the `bris` statement, causing the computer to immediately stop what it’s doing and leave the loop.

Challenge

Move the `scríobh(i)` line so that it also prints “5”.

Let’s fix our old code

This was the code we wrote earlier:

``````>-- Create an empty list
list := []

keep_going := fíor

nuair-a keep_going {
>-- Read from the console with léigh
text := léigh()

má text == "Stop" {
>-- They said "Stop"
keep_going = bréag
} nó {
>-- They didn't say "Stop".

>-- Add `text` to the end of the list
list += [text]
}
}
scríobh(list)``````

Now we can get rid of all that messy logic with `keep_going` and replace it all with a single `bris` statement! Check it out:

This code is much simpler and works exactly the same as before!

Keep Going!

In contrast to the `bris` statement, Setanta has another keyword called `chun-cinn`. “chun cinn” translates roughly as “forward”. Unlike `bris` which exits the loop completely, `chun-cinn` leaves the current iteration of the loop, and moves on to the next.

Check out this code:

That program has a list of colours, and for each colour it draws a circle randomly on the stage of that colour.

What if we want to skip the colours who’s name begins with a “g”? We could wrap the whole inside of the loop in a big `má` statement, but that would be a bit messy.

We can instead use the `chun-cinn` statement to skip to the next colour if the current colour begins with a “g”.

We can access elements of strings using their index just like we did with lists, by using square brackets (`[ ]`). To check if the name of the colour starts with “g” we just check if `colour[0] == "g"`, because 0 is the index of the first letter.

Let’s add the following check to the start of our loop:

``````má colour[0] == "g" {
chun-cinn
}``````

That will cause Setanta to stop and move on to the next iteration if the colour starts with “g”. Try it out:

As you can see by running the code, all the “g” colours (“glas”, “gorm”) are gone!