Variables & Mutability
In Wysna, variables are immutable by default. This design choice prevents unexpected state mutations across scopes and makes programs easier to reason about and optimize.
Immutable Bindings with let
Section titled “Immutable Bindings with let”When you declare a variable using let, its value cannot be modified after initialization:
fn main() -> unit { let port = 8080 print("Listening on port:", port)
# The following will trigger a compile-time error: # port = 9000 # Error: Cannot reassign immutable variable `port`}The compiler enforces this check during High-Level IR (HIR) verification.
Mutable Variables with let mut
Section titled “Mutable Variables with let mut”When a variable needs to change over time, declare it explicitly using let mut:
fn main() -> unit { let mut counter = 0 print("Initial:", counter)
counter = counter + 1 counter = counter + 5 print("Updated:", counter)}Notice that mutability is a property of the binding, not an inherent property of the data type itself.
Type Annotations vs. Type Inference
Section titled “Type Annotations vs. Type Inference”Wysna provides robust local type inference. You do not have to write type annotations when the type is obvious from the right-hand expression:
fn main() -> unit { # Inferred types let a = 42 # inferred as int let b = 3.14159 # inferred as float let c = "Wysna" # inferred as str let d = true # inferred as bool
# Explicit type annotations let count: int = 100 let ratio: float = 0.75 let title: str = "Systems Engineering"}Best Practice: While local variables can safely rely on inference, function parameters and return types must always have explicit type annotations. This guarantees that modules have clear, self-documenting contracts.