Assignment Operators
Assignment operators set or update variable values.
Overview
Assignment is how you store values in variables and update them over time.
Basic Assignment (=)
The simplest and most common operator:
import std:println
# Assign a value to a variable
x = 42
name = "Alice"
active = true
println(x) # 42
println(name) # Alice
Compound Assignment
Combine an operation with assignment for concise updates:
Addition Assignment (+=)
import std:println
x = 10
x += 5 # same as: x = x + 5
println(x) # 15
Subtraction Assignment (-=)
import std:println
x = 20
x -= 3 # same as: x = x - 3
println(x) # 17
Multiplication Assignment (*=)
import std:println
x = 5
x *= 4 # same as: x = x * 4
println(x) # 20
Division Assignment (/=)
import std:println
x = 100
x /= 4 # same as: x = x / 4
println(x) # 25
Modulo Assignment (%=)
import std:println
x = 17
x %= 5 # same as: x = x % 5
println(x) # 2
Increment and Decrement (++, --)
++ and -- are postfix operators that mutate the variable in place. There are
no prefix forms — ++x fails with Increment (++) can only be applied to variables.
Note that unlike C, x++ evaluates to the value after the increment:
import std:println
count = 0
count++
count++
println(count) # 2
count--
println(count) # 1
x = 1
y = x++
println(y) # 2 (the incremented value, not 1)
Assignment Semantics
Rebinding
Assignment in Suji rebinds the variable to a new value:
import std:println
x = 10
println(x) # 10
x = 20 # Rebind x to new value
println(x) # 20
x = "hello" # Can change type
println(x) # hello
Immutability
Strings and tuples are immutable. Lists and maps are mutable (some methods modify the value in place):
import std:println
list = [1, 2, 3]
list::push(4)
println(list) # [1, 2, 3, 4]
Destructuring Assignment
Tuple Destructuring
Unpack tuple values into variables. The target list is a bare comma-separated list
of names — do not wrap it in parentheses. (x, y) = (10, 20) fails with
Invalid assignment target:
import std:println
# Basic destructuring
x, y = (10, 20)
println("x: ${x}, y: ${y}") # x: 10, y: 20
# Any number of targets, as long as the arity matches
a, b, c, d = (1, 2, 3, 4)
println("${a}, ${b}, ${c}, ${d}") # 1, 2, 3, 4
# Ignore values with underscore
first, _, third = (1, 2, 3)
println("${first}, ${third}") # 1, 3
Nested destructuring is not supported. a, (b, c), d = … is a parse error;
unpack in two steps instead:
import std:println
outer, inner = (1, (2, 3))
p, q = inner
println("${outer}, ${p}, ${q}") # 1, 2, 3
Multiple Return Values
return a, b returns a tuple, which the caller can destructure:
import std:println
divide_with_remainder = |a, b| {
return (a / b)::floor(), a % b
}
quotient, remainder = divide_with_remainder(17, 5)
println("${quotient} remainder ${remainder}") # 3 remainder 2
Assignment vs Equality
Don’t confuse assignment (=) with equality (==):
import std:println
x = 5 # Assignment: set x to 5
# Equality check
match x == 5 {
true => println("x is 5"),
false => {},
}
# Assignment in condition would be an error
# match x = 5 { # Error: Assignment not allowed in condition
# ...
# }
Chained Assignment
Assign the same value to multiple variables:
import std:println
# Right-to-left evaluation
a = b = c = 10
println(a) # 10
println(b) # 10
println(c) # 10
Common Patterns
Accumulator
import std:println
numbers = [1, 2, 3, 4, 5]
sum = 0
loop through numbers with num {
sum += num
}
println(sum) # 15
Counter
import std:println
items = [3, -1, 7, 0, 12]
count = 0
loop through items with item {
match { item > 0 => { count++ } }
}
println("${count} valid items") # 3 valid items
Swap Values
import std:println
a = 10
b = 20
# Swap using tuple destructuring
a, b = (b, a)
println("a: ${a}, b: ${b}") # a: 20, b: 10
Update Configuration
import std:println
config = {
theme: "light",
lang: "en",
notifications: true
}
# Update single value
config["theme"] = "dark"
# Update multiple values
config["lang"] = "es"
config["notifications"] = false
println(config) # {theme: dark, lang: es, notifications: false}
Common Pitfalls
Pitfall 1: Forgetting Immutability
list = [1, 2, 3]
# push() modifies the list, but returns nil
result = list::push(4)
# list is now [1, 2, 3, 4], and result is nil
Pitfall 2: Assignment in Conditions
x = 5
# Typo: assignment instead of comparison
# match x = 10 { # Error
# ...
# }
# Correct: equality check
match x == 10 {
true => {
# ...
},
false => {},
}
Pitfall 3: Shadowing vs Mutation
import std:println
x = 10
# This creates a new binding in inner scope
{
x = 20 # Rebinds x
println(x) # 20
}
# x is now 20 (not shadowing in Suji, actual rebinding)
println(x) # 20
Pitfall 4: Compound Assignment Type Changes
import std:println
x = "10"
# This would be an error, so it is commented out:
# x += 5 -> Type error: Cannot add string and number
# Convert first
x = x::to_number()
x += 5
println(x) # 15
Best Practices
DO:
- Use compound assignment for concise updates
- Use destructuring for multiple return values
- Choose descriptive variable names
- Initialize variables before use
- Keep assignments simple and clear
DON’T:
- Confuse
=with== - Forget that operations return new values
- Use overly complex chained assignments
- Mutate external state unexpectedly
- Reuse variable names for different purposes
Examples
Running Total
import std:println
prices = [10.50, 25.00, 15.75, 30.00]
total = 0.0
loop through prices with price {
total = total + price
println("Subtotal: $${total}")
}
println("Final total: $${total}")
State Machine
import std:println
state = "idle"
process_event = |event| {
state = match (state, event) {
("idle", "start") => "running",
("running", "pause") => "paused",
("paused", "resume") => "running",
("running", "stop") => "idle",
_ => state,
}
}
process_event("start")
println(state) # running
Note the wildcard arm: a bare identifier in a pattern position is treated as a
string literal, not a binding, so (s, _) => s would try to match the literal
tuple ("s", "_"). Use _ and refer to the outer variable instead.
Fibonacci Sequence
import std:println
a = 0
b = 1
loop through (0..10) {
println(a)
a, b = (b, a + b) # Tuple swap and update
}
Build Configuration
import std:println
config = {}
# Build up configuration
config["env"] = "production"
config["debug"] = false
config["port"] = 8080
config["host"] = "0.0.0.0"
println(config) # {env: production, debug: false, port: 8080, host: 0.0.0.0}
Next Steps
- Learn about Arithmetic Operators
- Explore Language Overview
- Study Destructuring