Variables

Let's start with the basic building block of any programming language: variables!

To set a variable in Spawn use :=:

fn main() { number := 10 country := 'USA' }

Unlike other languages, Spawn variables are always initialized, which avoids various errors associated with the use of uninitialized variables.

Variable type

Unlike other languages, the type of variable is determined only by the expression to the right of the :=:

struct Foo {} fn main() { number := 10 // number has type i32 country := 'USA' // country has type string foo := Foo{} // foo has type Foo }

This approach allows you to write code not polluted by unnecessary type annotations, which makes the code more readable and compact, but, for example, if you want to define a variable with type u8, in the following code, the type of the variable number will be i32, not u8 as needed:

fn main() { number := 10 // number has type i32 println(number) }

To set a concrete type, use explicit casting via as:

fn main() { number := 10 as u8 // number has type u8 println(number) }

Now the type of the number variable will be u8 as we wanted. You can read more about type conversion in the Type conversion section.

Mutability

All variables in Spawn are immutable, which means that once a variable has been initialized, its value cannot be changed.

Create a file variables.sp and add the following code to it:

file=variables.sp fn main() { number := 10 number = 20 // error: cannot assign to `number` println(number) }

Now, if you try to build this code using spawnc variables.sp, the compiler will indicate that the variable number is immutable, but we are trying to change its value:

error(E0145): cannot assign to immutable variable `number`
 --> variables.sp:16:5:11
    |
 16 |     number = 20
    |     ^^^^^^

help: consider changing variable `number` to be mutable
 --> variables.sp:15:5:5
    |
 15 |     mut number := 10
    |     +++

As you can see, the compiler pointed to the place where we assign a new value to the number variable. When producing errors, the compiler tries as much as possible to help the developer correct the error found.

Always pay attention to the additional hints that the compiler displays after describing the error.

Let's follow the compiler's suggestion and make the number variable mutable by adding mut:

fn main() { mut number := 10 println(number) number = 20 // ok! println(number) }

And let's try to compile and run again:

spawnc --run variables.sp
10
20

So, the mut keyword before the variable name makes it mutable, which means we can change its value as many times as we want.

Shadowing

Unlike other languages, Spawn does not allow variables to be overridden in nested scopes:

fn main() { number := 10 if number > 20 { number := get_next_number() // error: redefinition of `number` } }

In the if block we define the variable number, but the same variable is defined in the parent block, so the compiler will throw an error about the variable being redefined. While variable overriding can be useful in some cases, it can often lead to unexpected results and long debugging sessions.

:= vs =

The variable definition operator := is very similar to =, which can cause confusion at the beginning. Let's look at the differences between them. The main difference is that := is used to define a new variable, while = is used to assign a value to an existing variable.

The following code is invalid because the number variable is not defined:

fn main() { number = 10 }

If you run the compiler, it will produce the following error:

error(E0079): unresolved identifier `number`
 --> variables.sp:15:12:13
    |
 15 |     number = 10
    |            ^ hint: use `:=` to declare variable

It's okay if you accidentally use = instead of :=, the compiler will always tell you how to fix the error.

Now that we know how to set variables, let's look at how to set constants!