Skip to main content

Control structures

Control structures are fundamental elements in programming that allow controlling the execution flow of a program. These structures allow making decisions, repeating code blocks, and handling errors (the latter, with try and catch, is in Errors and exceptions).

In JARU, all control structures, such as if, else, elsif, while, for, etc., must end with the keyword end. This indicates to the compiler that the control structure has ended. Using end is necessary to avoid syntax errors and to maintain a clean and easy-to-understand code structure. The rules for parentheses and then are in Basic syntax.

If-then-else flow​

The if-then-else control structure is one of the most basic control structures in programming. It's used to make decisions based on a given condition. The basic syntax is as follows:

if (condition) then
// code to execute if the condition is true
else
// code to execute if the condition is false
end

The elsif clause is an extension of if-then-else that allows evaluating multiple conditions in a single control structure. The code will execute in the first block where the condition is met:

if (condition1) then
// code to execute if condition1 is true
elsif (condition2) then
// code to execute if condition2 is true
else
// code to execute if no previous condition is true
end

Switch-case flow​

The switch-case control structure is a way to control program flow by selecting different paths based on a variable or expression. It's similar to using multiple nested if-else structures, but has the advantage of being more readable and easier to maintain.

switch (variable or expression)
case value1:
// instructions
case value2, value3:
// instructions
default:
// instructions
end

The expression is evaluated and compared with each of the case values. If a match is found, the instructions associated with that case are executed. If no match is found, the default instructions are executed.

func dayType(day)
switch (day)
case 1, 2, 3, 4, 5:
return "weekday"
case 6, 7:
return "weekend"
default:
return "does not exist"
end
end

println(dayType(3)) // weekday
println(dayType(7)) // weekend
println(dayType(9)) // does not exist
  • There is no fall-through from one case to the next. When the block of a case ends, the switch ends: you don't need break, and it doesn't work for that either (see break and continue).
  • A case accepts several values, separated by commas: case "A", "a":.
  • Values are compared as with ==. 1 matches 1.0, and strings match by their content. A list, a map or an object only matches itself, not another one with the same contents.
  • The values can be expressions: variables, constants, enumerations (case State.JUMPING:) or calculations.
  • The first matching case wins, in the order they are written. default only runs if none matches, even if it is written before the cases, and there can only be one.
  • If none matches and there is no default, nothing runs.
  • The expression goes in parentheses, and each case and the default end in :.

With strings:

var key = "a"
switch (key)
case "A", "a":
println("left")
case "D", "d":
println("right")
default:
println("another key")
end

With switch (true), each case can be a condition, and the first one that holds wins:

var score = 75
switch (true)
case score >= 90:
println("Excellent")
case score >= 50:
println("Pass")
default:
println("Fail")
end

For loop​

The for structure in JARU is used to perform a controlled loop. The basic syntax is as follows:

for (initialization; condition; increment) 
// loop body
end

The initialization is the expression executed at the beginning of the loop, usually a variable that will be used as a counter. The condition is an expression evaluated on each loop iteration; if the condition is false, the loop ends. The increment is the expression executed at the end of each loop iteration.

for (var i = 1; i <= 10; i++) 
println(i)
end

In this example, the initialization is var i = 1, the condition is i <= 10, and the increment is i++. Each time the loop executes, the value of variable i is printed and incremented by 1.

Infinite loop

You can create an infinite loop with for using the following syntax:

for (;;)
// loop body
end

Examples of for usage​

Iterate a set number of times:

for (var i = 0; i < 10; i++)
println("Iteration ", i)
end

Iterate over a list:

var myList = [1, 2, 3, 4, 5]
for (var i = 0; i < 5; i++)
println("The element at position ", i, " is ", myList[i])
end

Iterate in reverse order:

for (var i = 10; i > 0; i--)
println("Iteration ", i)
end

Extended for​

A unique feature of JARU is its extended for control structure, which adds filter functionality and alternative code to provide greater flexibility to programmers.

The extended for declaration in JARU follows this structure:

for (var i = start_value; i < end_value; i = i + increment_value; filter_condition) 
// code to execute when the filter condition is true
elfor
// alternative code to execute when the filter condition is false
end

Structure analysis​

  • Initialization: var i = start_value; This is where the loop control variable is initialized.
  • Condition: i < end_value; This is the condition evaluated before each loop iteration.
  • Update: i = i + increment_value; This is the operation performed after each loop iteration.
  • Filter: filter_condition A unique JARU feature that allows setting an additional condition that must be met for the code inside the loop to execute.
  • Alternative code: elfor Allows specifying an alternative code block that will execute when the filter condition is not met.
  • Termination: end Marks the end of the for block.

Extended for examples​

// FOR loop with filter (only prints even numbers)
for (var i = 0; i < 10; i = i + 1; i % 2 == 0)
println(i)
end

// FOR loop with filter and alternative (prints "odd" for odd numbers)
for (var i = 0; i < 10; i = i + 1; i % 2 == 0)
println(i)
elfor
println("odd")
end

Extended for use cases​

Processing only certain elements:

var list = [1, 2, 3, 4, 5, 6]
for (var i = 0; i < list.size(); i++; list[i] % 2 == 0)
println(list[i])
end

Handling exceptions or special conditions:

var data = [10, -3, 25]
for (var i = 0; i < data.size(); i++; data[i] >= 0)
println("Processing ", data[i])
elfor
println("Invalid data at index: ", i)
end

Nested loops with extended features:

var users = [
{"name": "Ana", "transactions": [50, 5000]},
{"name": "Luis", "transactions": [20]}
]

for (var i = 0; i < users.size(); i++)
var transactions = users[i]["transactions"]
for (var j = 0; j < transactions.size(); j++; transactions[j] > 1000)
println("Fraudulent transaction detected for user ", users[i]["name"])
elfor
println("Transaction OK: ", transactions[j])
end
end
Tip

The extended for is especially useful when you need to process data collections with complex conditions, avoiding the need to nest multiple if structures inside the loop.

Foreach loop​

The foreach control structure in JARU is used to iterate through elements of a collection, such as a list, map, or array. The basic syntax is as follows:

foreach (var element in collection)
// code to execute for each element
end

Where element is a temporary variable that takes the value of each element in the collection on each loop iteration. The loop body is executed for each element in the collection.

var list = [1, 2, 3, 4, 5]
foreach (var number in list)
println(number) // Shows 1, 2, 3, 4 and 5
end

In this case, the variable number takes the value of each element in the list on each iteration, and the code inside the foreach block runs for each element.

info

The loop automatically stops once all elements in the collection have been traversed.

What foreach goes through in each type (lists, maps, arrays and strings) and how to change the elements from inside the loop is in Walking through them with foreach.

While loop​

The while control structure in JARU is a loop that executes while a given condition is met. The condition is evaluated at the beginning of each iteration, and if it's true, the loop body executes. If the condition is false, the loop stops and continues with the next line of code.

while (condition)
// Code block to execute
end
Infinite loop

If you want an infinite loop with while, all you have to do is make the condition true:

while (true)
// Code block to execute
end

Example:

var i = 0
while (i < 10)
println("Variable i has value ", i)
i += 1
end

In this example, the condition is i < 10, so the loop executes 10 times, printing the value of variable i on each iteration.

Important

It's important to be careful to include a way to stop the loop, either by changing the condition within the loop body or using an additional control structure; otherwise, the loop will run indefinitely.

Until loop​

The until loop in JARU is used to repeat a code block until a certain condition is met.

until (condition) 
// code block
end

In this code, the condition is a boolean expression that is evaluated before each loop iteration. If the condition is false, the code block inside the loop will execute and then the condition will be evaluated again. This process will continue until the condition is true, at which point the loop will exit.

Example that prints numbers from 1 to 10:

var i = 1

until (i > 10)
println(i)
i++
end

Another example, a countdown from a given number to zero:

var number = 10
until (number == 0)
println(number)
number = number - 1
end
println("Liftoff!")

Difference between while and until​

Both until and while are flow control structures used to implement loops. The main difference is in how the exit condition is evaluated:

  • In until, the loop executes until the specified condition is true
  • In while, the loop executes while the condition is true
caution

It's important to note that the code block inside the loop must modify the condition in some way to avoid an infinite loop. Otherwise, the loop will run indefinitely.

Leaving a loop: break and continue​

  • break leaves the loop: the program carries on at the line after its end.
  • continue jumps to the next round. In a for, it goes through the increment first (i++); in while and until, it checks the condition again; in foreach, it moves on to the next element.

They work in for (also in the extended for), foreach, while and until.

for (var i = 1; i <= 10; i++)
if (i % 2 == 0) then
continue // skips the even numbers
end
if (i > 7) then
break // and stops after 7
end
print(i, " ")
end
println()
1 3 5 7

To search for something and stop searching as soon as it turns up:

var names = ["Ana", "Luis", "Eva", "Raúl"]
var position = -1
for (var i = 0; i < names.size(); i++)
if (names[i] == "Eva") then
position = i
break
end
end
println("Eva is at position ", position) // Eva is at position 2
  • With nested loops, they only affect the inner one: a break in the inner loop does not leave the outer one.
  • Inside a switch, they affect the loop that contains it. break does not leave the switch, but the loop:
var orders = ["forward", "turn", "jump", "stop", "forward"]
foreach (var order in orders)
switch (order)
case "stop":
break // leaves the foreach, not just the switch
case "jump":
continue // moves on to the next order
default:
println("Doing: ", order)
end
end
println("Done")
Doing: forward
Doing: turn
Done
  • Outside a loop they do not compile, with the error “Cannot use 'break' outside of a loop.”. They don't work in a function called from a loop either: they have to be inside the loop itself. This switch is not in any loop:
var option = 1
switch (option)
case 1:
println("one")
break // does not compile: there is no loop
end