Collections & Objects

Data Structures & Object-Oriented Programming

Dynamic arrays, hash maps with dot-notation access, for-in iterators, structs with synchronized method closures, and pattern matching.

Chapter 10

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

bramand — arrays
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!

bramand — hashes
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:

bmd — array & hash builtins
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

FunctionExact SignatureReturnDescription
lenlen(collection)INTEGERReturns number of elements in array, keys in hash, or UTF-8 runes in string.
pushpush(arr, elem)ARRAYAppends element to array, returning new array with element appended.
appendappend(arr, elem)ARRAYAlias for push.
poppop(arr)ARRAYReturns new array with the last element removed.
sliceslice(arr, start, [end])ARRAYExtracts slice from start up to end; supports negative offset indexing.
containscontains(container, item)BOOLEANReturns true if item is found in array, or key is present in hash.
deletedelete(hash, key)NULLRemoves entry matching key from hash in place.
keyskeys(hash)ARRAYReturns array containing all keys in the hash map.
valuesvalues(hash)ARRAYReturns array containing all values in the hash map.
sortsort(arr)ARRAYReturns new array with elements sorted in ascending natural order.
reversereverse(arr)ARRAYReturns 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:

bmd — array and hash 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:

bmd — array and hash spread
// 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!)
Fixed Sequences Hashable Primitive

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:

bramand — Tuple creation, indexing & destructuring
// 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:

bramand — Compound grid keys using tuples
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

FeatureArray ([a, b])Tuple ((a, b))
MutabilityMutable (arr[i] = v, push)Strictly Immutable
LengthDynamicFixed at allocation
Usable as Hash KeyNo (mutable reference)Yes (implements Hashable)
Memory LayoutOverallocated slice bufferCompact contiguous stack/heap slice
DestructuringPattern matching & let patternsMulti-variable destructuring (let (a, b) = tup)
Chapter 11

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.

bramand — for-in loops
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:

bmd — 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]
Chapter 12

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.

bramand — structs and 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.

bramand — struct embedding and composition
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.

bramand — callable struct and dunder methods
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.

bramand — enums
enum TaskStatus {
    PENDING,
    ACTIVE,
    DONE = 100,
    FAILED
}

print(TaskStatus.PENDING)         // 0
print(TaskStatus.ACTIVE)          // 1
print(TaskStatus.DONE)            // 100
print(TaskStatus.FAILED)          // 101
Chapter 13 Deep Destructuring Guards

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>):

bramand — Tuple destructuring with guard expressions
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:

bramand — Hash map pattern matching
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 FormSyntaxExampleDescription
Literalcase literal =>case 200, 201 =>Matches exact primitive value (Integer, Float, String, Boolean).
Tuple Patterncase (a, b) =>case (x, y) if x > y =>Unpacks fixed tuple elements into local variables with optional guard.
Array Patterncase [a, b] =>case [first, second] =>Unpacks array elements by positional index.
Hash Patterncase {"k": v} =>case {"status": 200} =>Extracts specified keys from a map and checks values.
Wildcardcase _ =>case _ => { fallback }Matches any value unconditionally without creating a binding.
Variable Catch-Allcase val =>case other => { log(other) }Matches any value and binds it to a scoped variable name.
Guardcase p if guard =>case n if n > 100 =>Evaluates boolean expression using bound variables before arm execution.
Sparse Collections

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:

bmd — sparse matrix representation
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]
Day 33 Standard High-Performance Tabular Data

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(...)).

bmd — Columnar DataFrame Projection & Vectorized Filtering
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 MethodSignatureReturnDescription
gt / ltcol.gt(val) / col.lt(val)ARRAY<bool>Vectorized strictly greater than / less than boolean mask.
gte / ltecol.gte(val) / col.lte(val)ARRAY<bool>Vectorized greater-or-equal / less-or-equal boolean mask.
eq / neqcol.eq(val) / col.neq(val)ARRAY<bool>Vectorized equality / inequality comparison mask.
sum / meancol.sum() / col.mean()FLOATVectorized summation and arithmetic mean computation.
min / maxcol.min() / col.max()NUMERICComputes minimum or maximum value in column vector.
add / mulcol.add(other) / col.mul(other)ColumnVectorVector-scalar or vector-vector pairwise arithmetic.