Variables and conditions
let, mut, values set later, blocks, and if with && and ||.
Variables
let names a value, and mut lets it change. Without a type, a variable
takes the type of its value.
let fixed = 5; // `i32`, from the value
let mut total: i64 = 0;Changing a variable declared without mut is an error:
[T0007]: cannot assign to immutable `count` --> src/main.peep:3:5 | 1 | fn main() {2 | let count = 1; | ----- declared without `mut` here3 | count = 2; | ^^^^^ | = help: write `let mut count`Compilation failed with 1 error(s)A let without a value is set by its first assignment. It must be set once
on every path before it is read:
let result: i32; // set below, once on each path
if value > 0 {
result = 1;
} else if value < 0 {
result = -1;
} else {
result = 0;
}If one path can skip the assignment, the compiler shows that path:
[T0039]: `value` is used before it is set --> src/main.peep:6:12 | 1 | fn pick(flag: bool) -> i32 {2 | let value: i32; | ----- declared here without a value...5 | }6 | return value; | ^^^^^ `value` is not set on every path to here | = help: set `value` on every path before this use, or give it a value where it is declaredCompilation failed with 1 error(s)A block can declare names of its own, which hide outer names until the block
ends. A parameter can be mut too.
// Variables: `let` names a value and `mut` lets it change. A `let` without
// a value is set by its first assignment, once on every path before it is
// read. A block may declare names of its own.
// Run: peeper run examples/04_variables.peep
fn sign(value: i32) -> i32 {
let result: i32; // set below, once on each path
if value > 0 {
result = 1;
} else if value < 0 {
result = -1;
} else {
result = 0;
}
return result;
}
fn next(mut count: i32) -> i32 { // a `mut` parameter
count = count + 1;
return count;
}
fn main() {
let fixed = 5; // `i32`, from the value
let mut total: i64 = 0;
total = total + fixed;
total = total * 2;
{
let fixed = 100; // hides the outer `fixed` in this block
total = total + fixed;
}
println("total:", total, "fixed:", fixed);
println("signs:", sign(-8), sign(0), sign(3));
println("next:", next(fixed));
}total: 110 fixed: 5
signs: -1 0 1
next: 6Conditions
if, else if and else take a bool. && and || skip their right side
when the left side already decides the answer, and ! negates.
// Conditions: `if`, `else if` and `else` take a `bool`. `&&` and `||` skip
// their right side when the left decides, and `!` negates.
// Run: peeper run examples/05_conditions.peep
fn describe(n: i32) {
if n < 0 {
println(n, "is negative");
} else if n == 0 {
println(n, "is zero");
} else {
println(n, "is positive");
}
}
fn noisy(value: bool) -> bool {
println(" noisy runs");
return value;
}
fn main() {
describe(-3);
describe(0);
describe(8);
println("and:", false && noisy(true)); // `noisy` does not run
println("or:", true || noisy(false)); // nor here
println("both:", true && noisy(true)); // here it does
println("not:", !(1 > 2));
}-3 is negative
0 is zero
8 is positive
and: false
or: true
noisy runs
both: true
not: true