5. Variables
5.1 Variable Declaration
Variables in MALDA are declared using the var keyword followed by the variable name and an optional initial value:
var x = 10;
var name = "Alice";
var isActive = true;
var pi = 3.14159;
Variables must be declared before use. The type is inferred from the initial value. For bindings that must never be reassigned, use const instead of var (see 5.3 Constant Declarations).
You may optionally add an informational type hint after the name. At interpret-time hints are documentation for you and the IDE, not runtime checks:
var name: Type? = value;
Example: var count: int = 0;, var msg: string = "hello";, or var p: Person = new Person();
--strict-types turns hint mismatches into analysis Errors. malda compile --mode transpile and publish refuse emit when analysis reports Errors; --lenient-types skips that gate. Known hint names include Tier 0 primitives (int, string, …), declared class/schema/sum-type names (same unit or imported modules), and built-in host classes (for example RestServer). The language server emits an Error by default when a hint disagrees with a literal, a new ClassName() expression, another identifier that carries a known hint, or a call result whose callee declares a return hint (for example var n: int = "abc";, var p: Person = 1;, n = s; when s: string, or var n: int = make(); when make() -> string). The same check covers assignments, call arguments, and return values against parameter/-> hints. Operators and built-in return types are not inferred.
5.2 Variable Assignment
After declaration, variables can be reassigned using the assignment operator =:
x = 20;
name = "Bob";
x = x + 1;
5.3 Constant Declarations
A binding declared with const instead of var cannot be reassigned. An initializer is required:
const MAX_RETRIES = 3;
const APP_NAME = "malda-demo";
print(MAX_RETRIES); // 3
Attempting to assign to a constant is a runtime error that names the binding:
const limit = 10;
limit = 20; // Runtime error: Cannot assign to const 'limit'.
Compound assignment (+=) and the increment operators are assignments too, so they fail on a constant for the same reason.
Constants Are Shallow
const freezes the binding, not the value it points to. A constant that holds an array, dictionary, or object still allows the contents to change:
const config = dict { "retries": 3 };
config["retries"] = 5; // Allowed: the dictionary is mutated, not the binding
print(config["retries"]); // 5
// config = dict { }; // Runtime error: Cannot assign to const 'config'.
Scope and Shadowing
Constants follow the same block scoping as var, and an inner scope may shadow an outer constant with its own binding:
const mode = "prod";
function describe() {
var mode = "local"; // Shadows the outer constant inside this function
return mode;
}
print(describe()); // "local"
print(mode); // "prod"
const for configuration values, limits, and lookup tables that must not drift during a run. Everything else stays var; MALDA does not require constants and does not optimize differently for them.
5.4 Destructuring
Destructuring allows you to extract values from arrays and objects into individual variables in a single statement.
Array Destructuring
Extract elements from an array into variables:
var arr = [10, 20];
var [x, y] = arr;
print(x); // Prints: 10
print(y); // Prints: 20
Rest Pattern: Use ...rest to capture remaining elements:
var arr = [1, 2, 3, 4, 5];
var [first, second, ...rest] = arr;
// first = 1, second = 2, rest = [3, 4, 5]
print(length(rest)); // Prints: 3
Notes:
- The array must have at least as many elements as variables (unless using rest pattern)
- The rest pattern must be at the last position
- You can skip elements using the wildcard pattern
_
Object Destructuring
Extract properties from an object into variables:
var user = { name: "Alice", age: 30, role: "admin" };
var { name, age } = user;
print(name); // Prints: "Alice"
print(age); // Prints: 30
Renaming: Extract properties with different variable names:
var user = { name: "Bob", age: 25 };
var { name: userName, age: userAge } = user;
print(userName); // Prints: "Bob"
print(userAge); // Prints: 25
Nested Destructuring: Extract from nested objects:
var data = {
user: { name: "Charlie", age: 35 },
role: "admin"
};
var { user: { name, age }, role } = data;
print(name); // Prints: "Charlie"
print(age); // Prints: 35
print(role); // Prints: "admin"
Destructuring Assignment
You can also use destructuring with assignment (for existing variables):
var x = 0;
var y = 0;
var arr = [10, 20];
[x, y] = arr; // Assigns 10 to x, 20 to y
print(x + y); // Prints: 30
var name = "";
var age = 0;
var user = { name: "David", age: 40 };
{ name, age } = user; // Assigns properties to variables
print(name); // Prints: "David"
print(age); // Prints: 40
Destructuring from Function Returns
Destructure values returned from functions:
function getPoint() {
return { x: 5, y: 10 };
}
var { x, y } = getPoint();
print(x + y); // Prints: 15
Error Handling
If a destructuring pattern doesn't match (e.g., array too short, missing object property), a runtime error is thrown:
try {
var arr = [1, 2];
var [x, y, z] = arr; // Error: array has only 2 elements
} catch (e) {
print("Destructuring failed: " + e);
}
- Use destructuring to make code more readable when working with structured data
- Destructuring is particularly useful when processing API responses or function returns
- You can combine array and object destructuring in nested structures
- Use the rest pattern to capture remaining elements when you don't know the exact length
5.5 Variable Scope
Variables in MALDA are block-scoped. A variable is accessible within the block where it is declared and any nested blocks.
Global Variables
Variables declared outside functions are global and accessible throughout the program:
var globalVar = 10;
function test() {
print(globalVar); // Can access global variable
}
test();
Local Variables
Variables declared inside a function are local to that function:
function test() {
var localVar = 20;
print(localVar); // Can access local variable
}
// print(localVar); // Error: localVar is not accessible here
Variable Shadowing
Local variables shadow global variables with the same name:
var x = 10; // Global variable
function test() {
var x = 20; // Local variable shadows global x
print(x); // Prints 20 (local)
}
test();
print(x); // Prints 10 (global)
Block Scope
Variables declared in blocks (if, while, for) are scoped to that block:
if (true) {
var blockVar = 30;
print(blockVar); // Can access blockVar
}
// print(blockVar); // Error: blockVar is not accessible here
See Also
- 4. Data Types - Types that variables can hold
- 8. Control Structures - Pattern matching and block scoping
- 6. Arrays - Arrays used in destructuring
- 9. Functions - Function scope and parameters