Data Structures & Object-Oriented Programming
Dynamic arrays, hash maps with dot-notation access, for-in iterators, structs with synchronized method closures, and pattern matching.
Arrays, Hashes & Index Expressions (arr[i] = v, hash[k] = v, obj.prop, .length)
BramandScript provides dynamic Arrays and Hash Tables (dictionaries) with rich index access, index mutation, and dot-property notation.
Arrays and Array Mutation
let items = [10, 20, 30, 40]
// Index reading (0-based)
print("First:", items[0]) // 10
// In-place index mutation
items[1] = 999
print("Modified:", items) // [10, 999, 30, 40]
// Property length access
print("Size:", items.length) // 4
Hashes & Dot-Property Notation
Hashes support any hashable key (Integers, Strings, Booleans). String keys can be accessed and assigned using either bracket syntax hash["key"] or ergonomic dot syntax hash.key!
let server = {
"host": "127.0.0.1",
"port": 8080,
"active": true
}
// Dot property reading
print("Host:", server.host)
// Dot property assignment (inserts or updates key!)
server.port = 9000
server.environment = "production"
print("Updated server:", server)
print("Key count:", server.length)
Collection Operations & Manipulation
BramandScript provides expressive built-in primitives for array and hash operations:
let nums = [3, 1, 4, 1, 5, 9]
// Adding elements
let expanded = push(nums, 26) // or append(nums, 26)
println("Expanded:", expanded) // [3, 1, 4, 1, 5, 9, 26]
// Slicing with positive and negative indices
let part = slice(nums, 1, 4) // [1, 4, 1]
let tail = slice(nums, -2, len(nums)) // [5, 9]
// Sorting and Reversing
let sortedList = sort(nums) // [1, 1, 3, 4, 5, 9]
let revList = reverse(nums) // [9, 5, 1, 4, 1, 3]
// Membership inspection
println("Has 4:", contains(nums, 4)) // true
// Hash inspection and deletion
let user = {"id": 101, "role": "admin", "active": true}
let userKeys = keys(user) // ["id", "role", "active"]
let userVals = values(user) // [101, "admin", true]
delete(user, "active")
println("Has active:", contains(user, "active")) // false
Collection Functions Reference Table
| Function | Exact Signature | Return | Description |
|---|---|---|---|
len | len(collection) | INTEGER | Returns number of elements in array, keys in hash, or UTF-8 runes in string. |
push | push(arr, elem) | ARRAY | Appends element to array, returning new array with element appended. |
append | append(arr, elem) | ARRAY | Alias for push. |
pop | pop(arr) | ARRAY | Returns new array with the last element removed. |
slice | slice(arr, start, [end]) | ARRAY | Extracts slice from start up to end; supports negative offset indexing. |
contains | contains(container, item) | BOOLEAN | Returns true if item is found in array, or key is present in hash. |
delete | delete(hash, key) | NULL | Removes entry matching key from hash in place. |
keys | keys(hash) | ARRAY | Returns array containing all keys in the hash map. |
values | values(hash) | ARRAY | Returns array containing all values in the hash map. |
sort | sort(arr) | ARRAY | Returns new array with elements sorted in ascending natural order. |
reverse | reverse(arr) | ARRAY | Returns new array with elements in reversed order. |
Pattern Destructuring (Arrays & Hashes)
Unpack collections cleanly with array pattern destructuring (including the rest operator ...) and hash key destructuring:
// 1. Array destructuring with rest operator
let [head, second, ...tail] = [10, 20, 30, 40, 50]
println("Head:", head) // 10
println("Second:", second) // 20
println("Tail:", tail) // [30, 40, 50]
// 2. Hash pattern destructuring
let user = { "name": "Bramand", "role": "Architect", "level": 99 }
let { name, role } = user
println("User:", name, "Role:", role)
// 3. Function signature destructuring
fn handle_coord({ x, y }) {
return sqrt(x * x + y * y)
}
Array & Hash Spread Expressions (...)
The spread operator (...) enables inline unpacking of array elements and deterministic dictionary merging with order preservation and key overrides:
// 1. Array Spread: In-line element unpacking
let mid = [2, 3]
let full = [1, ...mid, 4, 5]
println("Full array:", full) // [1, 2, 3, 4, 5]
// Multiple spreads & string character unpacking
let parts = [..."ab", ...[10, 20]]
println("Unpacked parts:", parts) // ["a", "b", 10, 20]
// 2. Hash Spread: Progressive map merging & property override
let defaults = { "host": "127.0.0.1", "port": 8080, "timeout": 30 }
let server_config = { ...defaults, "port": 9000, "ssl": true }
println("Server Port:", server_config.port) // 9000 (overridden!)
println("Server Host:", server_config.host) // "127.0.0.1" (preserved!)
First-Class Fixed Tuples ((a, b, c))
BramandScript provides first-class Fixed Tuples (TUPLE). Unlike dynamically resizable Arrays, Tuples are immutable, fixed-length sequences designed for multi-value returns, coordinate vectors, and compound hash keys.
1. Tuple Syntax & Immutability
Tuples are declared using parentheses. Single-element tuples require a trailing comma to distinguish from parenthesized grouping expressions:
// Constructing tuples
let empty_tuple = ()
let single_item = (42,)
let point = (10, 20, 30)
// Indexing and negative offsets
println("First:", point[0]) // 10
println("Last:", point[-1]) // 30
println("Length:", point.len) // 3
// Multi-variable destructuring
let (x, y, z) = point
println("Coordinates:", x, y, z) // 10 20 30
// Immutability: assigning to tuple indices produces an error
// point[0] = 99 // Compile/Runtime Error: cannot mutate immutable tuple
2. Tuples as Hash Map Keys (Hashable)
Because tuples are strictly immutable, they implement BramandScript's Hashable interface. This makes tuples the optimal data structure for multidimensional coordinates, compound cache keys, and graph edges:
let grid = {}
// Use (row, col) coordinate tuples as dictionary keys
grid[(0, 0)] = "Origin Station"
grid[(12, 45)] = "Waypoint Alpha"
grid[(88, 92)] = "Terminal Beta"
let query = (12, 45)
println("Located:", grid[query]) // "Waypoint Alpha"
3. Comparison: Arrays vs. Tuples
| Feature | Array ([a, b]) | Tuple ((a, b)) |
|---|---|---|
| Mutability | Mutable (arr[i] = v, push) | Strictly Immutable |
| Length | Dynamic | Fixed at allocation |
| Usable as Hash Key | No (mutable reference) | Yes (implements Hashable) |
| Memory Layout | Overallocated slice buffer | Compact contiguous stack/heap slice |
| Destructuring | Pattern matching & let patterns | Multi-variable destructuring (let (a, b) = tup) |
Iterators & for-in Loops (Arrays, Strings, Hashes, with break & continue)
BramandScript provides built-in for-in loops. The loop syntax optionally accepts an index variable before the item identifier.
let languages = ["Go", "BramandScript", "Rust", "Zig"]
// 1. Item-only iteration
for lang in languages {
print("Lang:", lang)
}
// 2. Index + Item iteration
for idx, lang in languages {
print("[" + str(idx) + "]", lang)
}
// 3. Iterating over strings (character by character)
for char in "Bramand" {
print("char:", char)
}
// 4. Early termination with break & continue
for i, val in [10, 20, 30, 40, 50] {
if val == 20 { continue }
if val == 40 { break }
print("Yielded:", val)
}
Resumable Generators & Lazy Streams (std/iter)
For processing large or infinite sequences without memory exhaustion, the std/iter module provides lazy generator streams:
import "std/iter" as iter
let naturals = iter.generator(fn(yield) {
let n = 1
while true {
yield n
n += 1
}
})
// Fluent chaining: take 5 items, map, and collect to array
let squares = naturals.take(5).map(fn(x) { return x * x; }).to_array()
println("Squares:", squares) // [1, 4, 9, 16, 25]
Structs & OOP Methods (struct Point { x, y, fn dist() { ... } })
BramandScript introduces clean object-oriented structs. A struct compiles into an instantiator closure that constructs a typed hash instance possessing the declared fields and bound methods.
// Define a 2D Point struct with methods
struct Point {
x, y
fn distanceSquared(otherX, otherY) {
let dx = x - otherX
let dy = y - otherY
return (dx ** 2) + (dy ** 2)
}
fn translate(offsetX, offsetY) {
x += offsetX
y += offsetY
}
}
// Instantiation
let pt = Point(10, 20)
// Field access
print("Initial coordinates:", pt.x, pt.y)
// Method invocation
print("Dist to (0,0):", pt.distanceSquared(0, 0))
// Mutation via method or direct dot access
pt.translate(5, -10)
pt.x = 100
print("After translation:", pt.x, pt.y)
Bidirectional State Synchronization
In BramandScript v0.1.0+, struct methods and instance properties maintain strict bidirectional synchronization. When a method executes, instance properties are populated into the method closure's free variables, and when the method completes, mutated variables are written back to the instance hash. Mutating fields directly (pt.x = 100) or via method calls (pt.translate(5, -10)) preserves total data integrity.
Struct Composition & Field Embedding (embed)
Structs can compose and delegate properties and methods from other structs using the embed keyword. Embedded fields and methods are automatically accessible on the outer instance without manual forwarding.
struct Speaker {
greeting,
fn speak(name) {
return greeting + " " + name
}
}
struct Bot {
embed Speaker,
id,
fn status() {
return "Bot#" + str(id) + " active"
}
}
let spk = Speaker("Hello")
let bot = Bot(spk, 42)
// Delegated field access & method invocation
print(bot.greeting) // "Hello"
print(bot.speak("World")) // "Hello World"
print(bot.status()) // "Bot#42 active"
Callable Struct Instances (__call__) & Magic Methods
Structs implementing the __call__ method become first-class callable objects that can be invoked like regular functions. The __str__ property provides custom string formatting, and __hash__ customizes map hashing.
struct Multiplier {
factor,
fn __call__(x) {
return x * factor
}
}
let triple = Multiplier(3)
print(triple(10)) // 30 (invokes __call__)
// Interface checking with implements()
let hasSpeak = implements(bot, ["speak", "status"])
print("Bot implements contract:", hasSpeak) // true
Enums & Tagged Constants (enum Status { ... })
First-class enums provide readable, type-safe symbolic enumerations with auto-incrementing integer values or explicit custom values.
enum TaskStatus {
PENDING,
ACTIVE,
DONE = 100,
FAILED
}
print(TaskStatus.PENDING) // 0
print(TaskStatus.ACTIVE) // 1
print(TaskStatus.DONE) // 100
print(TaskStatus.FAILED) // 101
Deep Pattern Matching & Guards (match ... case ... if ...)
BramandScript features top-tier pattern matching with structural destructuring, binding extraction, and boolean guard expressions. Expressions evaluate to values, support multi-pattern branches, wildcard discards (_), and variable catch-alls.
1. Structural Destructuring with Guards
Case arms can deconstruct Tuples, Arrays, and Hash maps, binding internal components to scoped variables while evaluating conditional guards (if <condition>):
let classify_point = fn(pt) {
return match pt {
case (0, 0) => {
"origin"
}
case (0, y) => {
"y-axis at " + str(y)
}
case (x, 0) => {
"x-axis at " + str(x)
}
case (x, y) if x == y => {
"diagonal point"
}
case (x, y) if x > 0 && y > 0 => {
"quadrant 1"
}
case (x, y) => {
"general point"
}
case _ => {
"not a coordinate"
}
}
}
println(classify_point((0, 0))) // "origin"
println(classify_point((4, 4))) // "diagonal point"
println(classify_point((5, 12))) // "quadrant 1"
2. Hash Map Pattern Matching
Hash patterns match specific key subsets, binding values directly for inspection:
let authorize = fn(user) {
return match user {
case { "role": "admin" } => {
"superadmin_granted"
}
case { "role": "editor", "level": lvl } if lvl >= 3 => {
"senior_editor"
}
case { "name": n } => {
"guest: " + n
}
case _ => {
"denied"
}
}
}
println(authorize({ "role": "admin" })) // "superadmin_granted"
println(authorize({ "role": "editor", "level": 4 })) // "senior_editor"
println(authorize({ "name": "Kiran" })) // "guest: Kiran"
3. Pattern Forms Reference
| Pattern Form | Syntax | Example | Description |
|---|---|---|---|
| Literal | case literal => | case 200, 201 => | Matches exact primitive value (Integer, Float, String, Boolean). |
| Tuple Pattern | case (a, b) => | case (x, y) if x > y => | Unpacks fixed tuple elements into local variables with optional guard. |
| Array Pattern | case [a, b] => | case [first, second] => | Unpacks array elements by positional index. |
| Hash Pattern | case {"k": v} => | case {"status": 200} => | Extracts specified keys from a map and checks values. |
| Wildcard | case _ => | case _ => { fallback } | Matches any value unconditionally without creating a binding. |
| Variable Catch-All | case val => | case other => { log(other) } | Matches any value and binds it to a scoped variable name. |
| Guard | case p if guard => | case n if n > 100 => | Evaluates boolean expression using bound variables before arm execution. |
Compressed Sparse Row (CSR) Matrices (std/math/sparse)
For massive sparse systems where 90%+ of elements are zero, CSRMatrix stores only non-zero entries via row pointers and column indices, minimizing memory footprint:
import "std/math/sparse" as sparse
let dense_grid = [
[10.0, 0.0, 0.0],
[ 0.0, 0.0, 20.0],
[30.0, 0.0, 40.0]
]
let csr = sparse.csr_from_dense(dense_grid)
println("Non-zero count:", csr.nnz()) // 4
println("Element at (2, 2):", csr.get(2, 2)) // 40.0
// Fast sparse matrix-vector multiplication (O(nnz))
let vec_result = csr.matmul_vec([1.0, 2.0, 3.0])
println("Sparse matmul vector:", vec_result) // [10.0, 60.0, 150.0]
Columnar DataFrames & Vectorized Operations (std/dataframe)
BramandScript provides a high-throughput tabular DataFrame engine with zero-copy columnar scanning, vectorized column operations (ColumnVector), boolean mask filtering, and direct in-memory relational SQL query integration (df.query(...)).
import "std/dataframe" as df;
// Create DataFrame from row records
let records = [
{"sensor": "temp_01", "reading": 32, "voltage": 3.2},
{"sensor": "temp_02", "reading": 45, "voltage": 4.5},
{"sensor": "temp_03", "reading": 89, "voltage": 8.9}
];
let frame = df.from_records(records);
// 1. Vectorized Column Extract and Summary Metrics
let voltage_col = frame.column("voltage");
println("Mean voltage:", voltage_col.mean()); // 5.533
println("Max voltage: ", voltage_col.max()); // 8.9
// 2. High-Performance Boolean Mask Slicing
let mask = voltage_col.gt(4.0); // [false, true, true]
let filtered_df = frame.filter_mask(mask);
println("Filtered Shape:", filtered_df.shape()); // [2, 3]
// 3. Bidirectional Columnar Conversions
let columnar_dict = frame.to_columnar();
// { sensor: ["temp_01", ...], reading: [32, 45, 89], voltage: [3.2, 4.5, 8.9] }
let reconstructed = df.from_columnar(columnar_dict);
// 4. In-Memory ANSI SQL Query Directly on DataFrame
let sql_df = frame.query("SELECT sensor, voltage FROM df WHERE voltage > 4.0 ORDER BY voltage DESC");
println("SQL Rows on DataFrame:", sql_df.to_records());
| ColumnVector Method | Signature | Return | Description |
|---|---|---|---|
gt / lt | col.gt(val) / col.lt(val) | ARRAY<bool> | Vectorized strictly greater than / less than boolean mask. |
gte / lte | col.gte(val) / col.lte(val) | ARRAY<bool> | Vectorized greater-or-equal / less-or-equal boolean mask. |
eq / neq | col.eq(val) / col.neq(val) | ARRAY<bool> | Vectorized equality / inequality comparison mask. |
sum / mean | col.sum() / col.mean() | FLOAT | Vectorized summation and arithmetic mean computation. |
min / max | col.min() / col.max() | NUMERIC | Computes minimum or maximum value in column vector. |
add / mul | col.add(other) / col.mul(other) | ColumnVector | Vector-scalar or vector-vector pairwise arithmetic. |