bop-lang 0.3.0

A small, embeddable, dynamically-typed programming language with zero dependencies
Documentation
// std.iter — functional helpers on arrays.
//
// Array-in, array-out. No lazy iterator protocol in v1 — if you
// care about the allocation, use a hand-written `for` loop.
// Every helper handles empty arrays gracefully and preserves
// relative element order.

// Apply `f` to each element; return a new array of results.
// `map([1, 2, 3], fn(x) { return x * 2 })` → `[2, 4, 6]`.
fn map(arr, f) {
    let out = []
    for x in arr { out.push(f(x)) }
    return out
}

// Keep only the elements for which `pred(x)` is truthy.
fn filter(arr, pred) {
    let out = []
    for x in arr {
        if pred(x) { out.push(x) }
    }
    return out
}

// Fold over the array left-to-right with a two-arg combiner.
// `reduce([1, 2, 3], 0, fn(acc, x) { return acc + x })` → `6`.
fn reduce(arr, initial, combine) {
    let acc = initial
    for x in arr { acc = combine(acc, x) }
    return acc
}

// First `n` elements (or the whole array if it's shorter).
// Negative `n` yields an empty array.
fn take(arr, n) {
    if n <= 0 { return [] }
    let out = []
    let i = 0
    for x in arr {
        if i >= n { return out }
        out.push(x)
        i = i + 1
    }
    return out
}

// Drop the first `n` elements. Negative `n` yields a full
// copy; `n >= arr.len()` yields an empty array.
fn drop(arr, n) {
    if n <= 0 { return arr + [] }
    let out = []
    let i = 0
    for x in arr {
        if i >= n { out.push(x) }
        i = i + 1
    }
    return out
}

// Pair elements from two arrays. Stops at the shorter array's
// length. `zip([1, 2], ["a", "b"])` → `[[1, "a"], [2, "b"]]`.
fn zip(a, b) {
    let out = []
    let n = a.len()
    let m = b.len()
    let k = if n < m { n } else { m }
    let i = 0
    while i < k {
        out.push([a[i], b[i]])
        i = i + 1
    }
    return out
}

// Pair each element with its 0-based index.
// `enumerate(["a", "b"])` → `[[0, "a"], [1, "b"]]`.
fn enumerate(arr) {
    let out = []
    let i = 0
    for x in arr {
        out.push([i, x])
        i = i + 1
    }
    return out
}

// `true` if `pred(x)` is truthy for every `x` (and for an empty
// array, by vacuous convention).
fn all(arr, pred) {
    for x in arr {
        if !pred(x) { return false }
    }
    return true
}

// `true` if `pred(x)` is truthy for at least one `x`.
fn any(arr, pred) {
    for x in arr {
        if pred(x) { return true }
    }
    return false
}

// Count elements for which `pred(x)` is truthy.
fn count(arr, pred) {
    let c = 0
    for x in arr {
        if pred(x) { c = c + 1 }
    }
    return c
}

// First element for which `pred(x)` is truthy, or `none` if no
// match. Caller is expected to pattern-match / null-check.
fn find(arr, pred) {
    for x in arr {
        if pred(x) { return x }
    }
    return none
}

// Index of the first matching element, or `-1` if no match.
fn find_index(arr, pred) {
    let i = 0
    for x in arr {
        if pred(x) { return i }
        i = i + 1
    }
    return -1
}

// Flatten an array of arrays one level down.
// `flatten([[1, 2], [3, 4]])` → `[1, 2, 3, 4]`.
fn flatten(arr) {
    let out = []
    for inner in arr {
        for x in inner { out.push(x) }
    }
    return out
}

// Sum of a numeric array. Empty → 0.
fn sum(arr) {
    let s = 0
    for x in arr { s = s + x }
    return s
}

// Product of a numeric array. Empty → 1 (multiplicative
// identity; matches NumPy / Python's `math.prod`).
fn product(arr) {
    let p = 1
    for x in arr { p = p * x }
    return p
}

// Min / max of a numeric array. Raises on empty input via a
// deliberate type error so callers notice.
fn min_array(arr) {
    let n = arr.len()
    if n == 0 { return none[0] }
    let m = arr[0]
    let i = 1
    while i < n {
        if arr[i] < m { m = arr[i] }
        i = i + 1
    }
    return m
}

fn max_array(arr) {
    let n = arr.len()
    if n == 0 { return none[0] }
    let m = arr[0]
    let i = 1
    while i < n {
        if arr[i] > m { m = arr[i] }
        i = i + 1
    }
    return m
}