Control flow in Golo is imperative and has the usual constructions found in upstream languages.
Golo supports the traditional if / else constructions, as in:
if goloIsGreat() {
println("Golo Golo")
}
if (someCondition) {
doThis()
} else if someOtherCondition {
doThat()
} else {
doThatThing()
}The condition of an if statement does not need parenthesis. You may add some to clarify a more
elaborated expression, though.
Golo offers a versatile case construction for conditional branching. It may be used in place of
multiple nested if / else statements, as in:
function what = |obj| {
case {
when obj oftype String.class {
return "String"
}
when obj oftype Integer.class {
return "Integer"
}
otherwise {
return "alien"
}
}
}A case statement requires at least 1 when clause and a mandatory otherwise clause. Each clause
is being associated with a block. It is semantically equivalent to the corresponding if / else
chain:
function what = |obj| {
if obj oftype String.class {
return "String"
} else if obj oftype Integer.class {
return "Integer"
} else {
return "alien"
}
}when clauses are being evaluated in the declaration order, and only the first satisfied
one is being executed.
The match statement is a convenient shortcut for cases where a case statement would be used to
match a value, and give back a result. While it may resemble pattern matching operators in some
other languages it is not fully equivalent, as Golo does not support destructuring.
match is a great addition to the Golo programmer:
let item = "foo@bar.com"
let what_it_could_be = -> match {
when item: contains("@") then "an email?"
when item: startsWith("+33") then "a French phone number?"
when item: startsWith("http://") then "a website URL?"
otherwise "I have no clue, mate!"
}
# prints "an email?"
println(what_it_could_be(item))The values to be returned are specified after a then keyword that follows a boolean expression to
be evaluated.
Like case statements, a match construct needs at least one when clause and one otherwise
clause.
While loops in Golo are straightforward:
function times = |n| {
var times = 0
while (times < n) { times = times + 1 }
return times
}The parenthesis in the while condition may be omitted like it is the case for if statements.
This is the most versatile loop construction, as it features:
The following function shows a for loop:
function fact = |value, n| {
var result = 1
for (var i = 0, i < n, i = i + 1) {
result = result * value
}
return result
}As you can see, it is very much like a for loop in Java, except that:
for loop elements are separated by ',' instead of ';', and
Again, this choice is dictated by the pursue of simplicity.
Golo provides a "for each" style of iteration over iterable elements. Any object that is an instance
of java.lang.Iterable can be used in foreach loops, as in:
function concat_to_string = |iterable| {
var result = ""
foreach item in iterable {
result = result + item
}
return result
}In this example, item is a variable within the foreach loop scope, and iterable is an object
that is expected to be iterable.
You may use parenthesis around a foreach expression, so foreach (foo in bar) is equivalent to
foreach foo in bar.
Although Java arrays (Object[]) are not real objects, they can be used with foreach loops.
Golo provides a iterator() method for them.
Although not strictly necessary, the break and continue statements can be useful to simplify
some loops in imperative languages.
Like in Java and many other languages:
break exits the current inner-most loop, and
continue skips to the next iteration of the current inner-most loop.
Consider the following contrived example:
module test
function main = |args| {
var i = 0
while true {
i = i + 1
if i < 40 {
continue
} else {
print(i + " ")
}
if i == 50 {
break
}
}
println("bye")
}It prints the following output:
40 41 42 43 44 45 46 47 48 49 50 bye
Golo does not support break statements to labels like Java does. In fact, this is a goto
statement in disguise.
Some programming languages return values from selected control flow constructions, with the returned value being the evaluation of the last statement in a block. This can be handy in some situations such as the following code snippet in Scala:
println(if (4 % 2 == 0) "even" else "odd")
The Golo original author recognizes and appreciates the expressiveness of such construct. However, he often finds it harder to spot the returned values with such constructs, and he thought that trading a few keystrokes for explicitness was better than shorter construct based in implicitness.
Therefore, most Golo control flow constructions do not return values, and programmers are instead
required to extract a variable or provide an explicit return statement.