Skip to main content
Variables in Walrus are dynamically typed and can hold any value type. This guide covers variable declaration, assignment, and scoping rules.

Variable declaration

Use the let keyword to declare variables:
let name = "Alice";
let age = 30;
let is_active = true;
let items = [1, 2, 3];
Variable declarations with let create a new variable in the current scope.

Assignment

Once declared, you can reassign variables to new values:
let x = 10;
println(x);  // 10

x = 20;
println(x);  // 20

// Can change types
x = "now a string";
println(x);  // now a string

Multiple assignments

let a = 5;
let b = 10;
let c = 15;

println(a);  // 5
println(b);  // 10
println(c);  // 15

Dynamic typing

Walrus is dynamically typed, meaning variables can hold values of any type and can change types:
let value = 42;              // Integer
println(type(value));        // int

value = 3.14;                // Now a float
println(type(value));        // float

value = "text";              // Now a string
println(type(value));        // string

value = [1, 2, 3];           // Now a list
println(type(value));        // list

Variable scope

Local scope

Variables declared inside a block are local to that block:
let x = 10;  // Global scope

if true {
    let y = 20;  // Local to if block
    println(x);  // 10 (can access global)
    println(y);  // 20
}

println(x);  // 10
println(y);  // Error: y not defined in this scope

Function scope

Function parameters and variables declared in functions are local to that function:
let global_var = "global";

fn example : param {
    let local_var = "local";
    println(param);       // Accessible
    println(local_var);   // Accessible
    println(global_var);  // Can access global
}

example("test");
println(local_var);  // Error: not defined

Shadowing

Inner scopes can shadow outer variables:
let x = 10;
println(x);  // 10

if true {
    let x = 20;  // Shadows outer x
    println(x);  // 20
}

println(x);  // 10 (outer x unchanged)

Global variables

Variables declared at the top level are global and accessible from anywhere:
let global_count = 0;

fn increment : {
    global_count = global_count + 1;
}

increment();
increment();
println(global_count);  // 2
Modifying global variables from functions can make code harder to understand. Consider using function parameters and return values instead.

Compound assignment

Walrus supports compound assignment operators:

Arithmetic compound assignment

let x = 10;

x += 5;   // Same as: x = x + 5
println(x);  // 15

x -= 3;   // Same as: x = x - 3
println(x);  // 12

x *= 2;   // Same as: x = x * 2
println(x);  // 24

x /= 4;   // Same as: x = x / 4
println(x);  // 6

x %= 4;   // Same as: x = x % 4
println(x);  // 2

String concatenation

let message = "Hello";
message += " World";
println(message);  // Hello World

Collection compound assignment

// Lists
let nums = [1, 2, 3];
nums += [4, 5];
println(nums);  // [1, 2, 3, 4, 5]

// Dictionaries
let config = {"debug": true};
config += {"port": 8080};
println(config);  // {"debug": true, "port": 8080}

Working with collections

List element assignment

Modify list elements by index:
let numbers = [10, 20, 30, 40];

numbers[0] = 15;    // Update first element
numbers[-1] = 45;   // Update last element

println(numbers);   // [15, 20, 30, 45]

Dictionary entry assignment

Add or update dictionary entries:
let person = {"name": "Alice"};

person["age"] = 30;           // Add new entry
person["name"] = "Bob";       // Update existing entry

println(person);  // {"name": "Bob", "age": 30}

Nested structure assignment

let data = {
    "users": [
        {"name": "Alice", "score": 100},
        {"name": "Bob", "score": 85}
    ]
};

// Update nested value
data["users"][0]["score"] = 105;

println(data["users"][0]);  // {"name": "Alice", "score": 105}

Uninitialized variables

You must initialize variables when declaring them. Walrus does not support uninitialized variables:
let x;  // Error: must provide initial value
If you need a placeholder, use void:
let result = void;

if condition {
    result = calculate_value();
}

if result != void {
    println(result);
}

Constants

Walrus doesn’t have a special const keyword, but by convention, you can use uppercase names for values that shouldn’t change:
let MAX_RETRIES = 3;
let DEFAULT_TIMEOUT = 30;
let API_VERSION = "v2";

// These are not enforced as immutable, just a convention

Variable naming conventions

Practical examples

Counter pattern

let count = 0;

for i in 0..10 {
    if i % 2 == 0 {
        count += 1;
    }
}

println(f"Even numbers: {count}");  // Even numbers: 5

Accumulator pattern

let numbers = [1, 2, 3, 4, 5];
let sum = 0;

for num in numbers {
    sum += num;
}

println(f"Sum: {sum}");  // Sum: 15

Swap variables

let a = 10;
let b = 20;

// Swap using temporary variable
let temp = a;
a = b;
b = temp;

println(a);  // 20
println(b);  // 10

Building collections

// Build a list incrementally
let results = [];

for i in 0..5 {
    results.push(i * i);
}

println(results);  // [0, 1, 4, 9, 16]

// Build a dictionary incrementally
let scores = {};
scores["Alice"] = 95;
scores["Bob"] = 87;
scores["Charlie"] = 92;

println(scores);

Best practices

Declare variables near where they’re first used:
// Good
if needs_calculation {
    let result = complex_calculation();
    println(result);
}

// Less clear
let result = void;
// ... many lines of code ...
if needs_calculation {
    result = complex_calculation();
    println(result);
}
Choose names that explain what the variable represents:
// Good
let remaining_attempts = 3;
let user_is_authenticated = true;
let error_message = "Connection failed";

// Avoid
let r = 3;
let flag = true;
let msg = "Connection failed";
Prefer passing data through function parameters:
// Good
fn calculate_total : items {
    let total = 0;
    for item in items {
        total += item["price"];
    }
    return total;
}

let cart = [{"price": 10}, {"price": 20}];
let total = calculate_total(cart);

// Avoid (using global)
let cart = [{"price": 10}, {"price": 20}];
let total = 0;

fn calculate_total : {
    for item in cart {
        total += item["price"];
    }
}

calculate_total();

Next steps

Operators

Learn about arithmetic, comparison, and logical operators

Control flow

Explore if/else, loops, and control flow statements

Build docs developers (and LLMs) love