Mutable
A let variable keeps its first value for good. A var variable may change: after it is declared, = gives it a new value as often as the program needs. That is the whole difference — and the reason let is the default. Writing var tells the reader "watch this name, it moves".
Declaring and assigning
var is declared exactly like let, with the type inferred the same way. Assignment then replaces the value:
var score = 10;
score = 25;
score = score + 5;
The right-hand side is worked out first, so score = score + 5 reads the old value (25) and stores the new one (30).
Declaring now, assigning later
A var may be declared with a type and no value — as long as it gets one before anything reads it:
var bonus: int;
bonus = score * 2;
Assignment copies the value
saved takes the value level holds at that moment. Changing level afterwards does not reach back into it:
var level = 1;
let saved = level;
level = 2;
flowchart LR
subgraph before ["after let saved = level;"]
l1["level: 1"]
s1["saved: 1"]
end
subgraph after ["after level = 2;"]
l2["level: 2"]
s2["saved: 1"]
end
before --> afterEach variable owns its own copy. Later, the Ownership part shows what happens with larger values, and how to move one instead of copying it.
let or var?
| Use | When |
|---|---|
let | The value is set once — most variables. |
var | The value has to change: a counter, a running total, a position. |
Start with let. If the compiler tells you a variable needs to change, switch that one to var.
The program
The whole lesson is one package in the Examples repository. Its comments explain every step.
// A `let` variable keeps its first value for good. A `var` variable may change: after it is
// declared, `=` gives it a new value, as often as the program needs. That is the whole difference,
// and it is why `let` is the default — `var` says "watch this name, it moves".
import Io::PrintLine;
func Main() -> int {
// `var` is declared exactly like `let`, and its type is inferred the same way.
var score = 10;
PrintLine("score {}", score);
// Assignment replaces the value. The right-hand side is worked out first, so it may use the
// variable's own old value.
score = 25;
PrintLine("score {}", score);
score = score + 5;
PrintLine("score {}", score);
// A `var` may be declared with a type and no value, so long as it is given one before
// anything reads it.
var bonus: int;
bonus = score * 2;
PrintLine("bonus {}", bonus);
// Assigning copies the value. `saved` took the 1 that `level` held at that moment, and
// changing `level` afterwards does not reach back into it.
var level = 1;
let saved = level;
level = 2;
PrintLine("level {}", level);
PrintLine("saved {}", saved);
// What may change is the value, never the type. `score` became an `int` when it was declared
// and stays one, and a variable cannot be read before it has a value:
//
// score = 2.5;
// error: cannot assign 'float64' to 'int'
//
// var total: int;
// PrintLine("{}", total);
// error: variable 'total' is used before it is initialized
return 0;
}
Run it
cd Examples/Basics/Mutable
rux run
score 10
score 25
score 30
bonus 60
level 2
saved 1
Common mistakes
The value of a
var may change; its type never does. score became an int when it was declared, so score = 2.5; fails with error: cannot assign 'float64' to 'int'.var total: int; followed by PrintLine("{}", total); fails with error: variable 'total' is used before it is initialized.Try it yourself
- Start a
var count = 0;, add 1 to it three times, and print it after each step. - Declare
var message: char8[..];with no value, assign it on the next line, and print it. - Change
var scoreback tolet scoreand read the message the compiler gives for the first assignment.
Learn more
varand mutability in the Rux Reference- Assignment —
+=,++and the other ways to update a variable