Variables & Scope
Variable names can contain letters or numbers, but must start with a letter. By convention multi-word names are written in camelCase.
foo
bar3
myLongVariableName
i18n
New variables don't have to be declared specially. Assigning to an unused variable name will create that variable.
foo = 5
foo = foo + 1
It's possible to assign to any variable at essentially any point, but the exact behaviour depends on the surrounding context – assignment to foo might update foo, or create a new variable with the name foo.
Function scopes
Functions cannot alter a variable outside of the function body. For example
x = 1
fn foo() {
x = 2
}
foo()
println(x) # => 1
foo is free to create and use a variable called x, but it is a new variable unrelated to the x in global scope. The same applies to closures.
Control flow scopes
Variables assigned inside a while, for or if/else will update an outside variable if it exists.
fn foo() {
x = 1
if true {
x = 2
}
return x
}
println(foo()) # => 2
However, if there is no outer variable with the same name, the variable only exists inside the if body.
fn foo() {
if true {
x = 2
}
return x
}
println(foo()) # => error: No variable named `x`
If this code were to work, it would nevertheless break if the if condition were false. Preventing variables from "leaking" in this case simplifies things: a variable is either defined or it isn't, regardless of any runtime values.
If you need to initialise a variable inside a loop or conditional, just set it to nil first.
fn foo() {
x = nil
if true {
x = 2
}
return x
}
println(foo()) # => 2
Let scope
let allows you to create a new variable regardless of whether one already exists.
fn foo() {
x = 1
let x = 2 {
# ...
}
return x
}
println(foo()) # => 1
Inside the let body, assignments work the same as in loops and conditionals.