Skip to main content

Loops & Branches

Raven uses {} to show the start and end of code blocks, so the basic syntax will look familiar to users of other languages.

See Variables & Scope for details on how variables assignments work inside if, while and for.

Conditionals

Here's a simple conditional.

test.rv
if ((2 + 2) == 5) {
println("Freedom is Slavery")
} else {
println("Some numbers are more equal than others")
}
julia> Raven.exec("test.rv")
Some numbers are more equal than others
caution

Raven doesn't have any operator precedence yet, so in general it's a good idea to add brackets () around operators.

Conditionals are values, so can be assigned to a variable or passed to a function.

x = if ((2+2) == 5) {
"Freedom is Slavery"
} else {
"Some numbers are more equal than others"
}
println(x)

Conditionals can have any number of else if branches, and the last else is optional.

if ((2 + 2) == 5) {
println("Something has gone seriously wrong")
} # otherwise do nothing
if ((2 + 2) == 3) {
println("Undershot it")
} else if ((2 + 2) == 5) {
println("Overshot it")
} else {
println("We're probably OK")
}

While Loops

Here's a loop that enthusiastically prints "hello, world" forever (use Ctrl-C to interrupt).

test.rv
while true {
println("Hello, World!")
}
julia> Raven.exec("test.rv")
Hello, World!
Hello, World!
Hello, World!
...

Inside while loops you can also use the statements break and continue. break immediately exits the loop. continue skips the remainder of the loop body, going back to the beginning.

info

Like if, loops are technically expressions, so can be assigned to a variable. However, their value is always nil.

For Loops

Here's a for loop, printing the first 10 square numbers.

test.rv
for i in range(1, 10) {
println(i^2)
}
julia> Raven.exec("test.rv")
1
4
9
...

for loops can use break and continue, just like while loops.

Short-circuit operators

The operators a && b and a || b behave like logical "and" and "or" respectively, but they only evaluate b if necessary.

test.rv
fn foo() {
println("foo ran")
return true
}

fn bar() {
println("bar ran")
return false
}

println("running &&")
foo() && bar()

println("running ||")
foo() || bar()
running &&
foo ran
running ||
foo ran
bar ran

In the first case, foo() is true, which means foo() && bar() must be true regardless of what bar() is – we can skip it. In the second case, foo() || bar() is true if and only if bar() is, so we have to evaluate it and check.