Stof Docs
Star on GitHubStof WebsiteDiscordContact Us
  • 🚀Welcome
  • â„šī¸Resources & Information
  • Book
    • Data Interface
    • Introduction & Design
    • Host Environments
      • Rust
      • TypeScript
        • Extend Stof
        • Import Statement
    • Data Interchange
      • JSON to Stof
      • Importing and Parsing Data
      • Exporting Data
      • REST and Restructure
    • Configuration Files
    • Schemas
      • Renaming Fields
      • Removing Fields
      • Validation & Transformation
        • Example Access
      • Nested Schemas
    • Orchestration
  • Common Concepts
    • Objects
    • Primitive Types
    • Functions
    • Fields
    • Object Types
    • Imports
    • Error Handling
    • Units
    • Casting/Conversions
  • Reference
    • CLI
      • 🏃Run
      • đŸ§ĒTest
      • 📚CLI Libraries
        • Filesystem Library
        • Time Library
        • HTTP Library
    • Stof Language
    • Libraries
      • Standard Library
      • Array/Vector Library
      • Number Library
      • String Library
      • Object Library
      • Function Library
      • Set Library
      • Map Library
      • Data Library
      • Tuple Library
      • Blob Library
      • Boolean Library
    • đŸĒ§Formats
Powered by GitBook
On this page
  • Common Value Functions
  • Array.toString(array: vec): str
  • Array.or(array: vec, ...): unknown
  • Vector Functions
  • Array.append(array: vec, other: vec): void
  • Array.push(array: vec, ...): void
  • Array.pop(array: vec, index?: int | unknown): unknown | null
  • Array.reverse(array: vec): void
  • Array.reversed(array: vec): vec
  • Array.len(array: vec): int
  • Array.empty(array: vec): bool
  • Array.any(array: vec): bool
  • Array.at(array: vec, index: int): unknown
  • Array.first(array: vec): unknown | null
  • Array.last(array: vec): unknown | null
  • Array.join(array: vec, separator: str): str
  • Array.contains(array: vec, value: unknown): bool
  • Array.find(array: vec, other: unknown): int
  • Array.remove(array: vec, other: unknown): unknown | null
  • Array.removeLast(array: vec, other: unknown): unknown | null
  • Array.removeAll(array: vec, other: unknown): vec
  • Array.insert(array: vec, index: int, ...values: unknown): void
  • Array.set(array: vec, index: int, ...values: unknown): void
  • Array.iter(array: vec, func: fn): void
  • Array.retain(array: vec, func: fn): void
  • Array.sort(array: vec, func?: fn): void

Was this helpful?

  1. Reference
  2. Libraries

Array/Vector Library

Stof's standard array/vector library ("Array").

PreviousStandard LibraryNextNumber Library

Last updated 4 months ago

Was this helpful?

In Stof, arrays and vectors are the same thing. We support both nomenclatures because it is common for "array" to be used in data formats, however, an array in most programming contexts is a fixed-capacity compound type that cannot grow in size. In Stof, arrays are implemented as vectors, and the "vec" type makes more sense. This separation also helps distinguish the arrays declared in a document from the "runtime" vectors used to manipulate data.

Anywhere a vec type is supported, a Box<vec> type is also supported. If a boxed value is passed in and manipulated, it will be manipulated anywhere else it is also referenced. See Primitive Types for more information on the Box type.

Common Value Functions

Array.toString(array: vec): str

#[test]
fn test() {
    pln([1, 2, 3].toString());       // [1, 2, 3]
    pln(Array.toString([4, 5, 6]));  // [4, 5, 6]
}

Array.or(array: vec, ...): unknown

Returns the first non-empty (null or void) argument, just like the "or" function.

#[test]
fn test() {
    let val = [1, 2, 3];
    let default = [4, 5];
    
    let x = val.or(default, []);
    assertEq(x, [1, 2, 3]);
    
    val = null;
    let y = val.or(default, 42, "hello", []);
    assertEq(y, [4, 5]);
}

Vector Functions

Array.append(array: vec, other: vec): void

Appends another vector into this array, leaving the other empty. If not boxed, "other" will be cloned when this function is called, and the original vector maintains its values.

#[test]
fn append() {
    let a = [1, 2, 3, 4, 5];
    let b = [6, 7, 8, 9];
    a.append(b);
    assertEq(a, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
    assertEq(b, [6, 7, 8, 9]);
}

#[test]
fn append_boxed() {
    let a = [1, 2, 3, 4, 5];
    let b = box([6, 7, 8, 9]);
    a.append(b);
    assertEq(a, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
    assertEq(b, []);
}

Array.push(array: vec, ...): void

Pushes all arguments to the end of the array in order, as they are given.

#[test(["hi"])]
fn push(): vec {
    let array = [];
    array.push("hi");
    return array;
}

Array.pop(array: vec, index?: int | unknown): unknown | null

Pop a value from this array. If an index is not provided, the last element of the array will be removed and returned (null if the array is empty).

If the index is a number, it will be treated as the position within the array to remove and return. An error will be thrown if this index is greater than or equal to the length of the array (indices start at zero).

If the index is a value other than a number, the first value in the array that equals the index value will be removed and returned. If no value in the array equals the index, null is returned.

It is preferred to use the "remove", "removeLast", or "removeAll" functions for removing values by equality rather than by index/position.

#[test(["hi"])]
fn pop(): vec {
    let array = ["hi", "there"];
    assertEq(array.pop(), "there");
    return array;
}

#[test([1, 2, 4, 5, 6])]
fn pop_at(): vec {
    let array = [1, 2, 3, 4, 5, 6];
    assertEq(array.pop(2), 3); // if given a number param, it is treated as an index
    return array;
}

#[test(["a", "c", "d", "e"])]
fn pop_val(): vec {
    let array: vec = ["a", "b", "c", "d", "e"];
    assertEq(array.pop("b"), "b");
    return array;
}

Array.reverse(array: vec): void

Reverses the array in place.

#[test]
fn reverse() {
    let array = [1, 2, 3, 4];
    array.reverse();
    assertEq(array, [4, 3, 2, 1]);
}

Array.reversed(array: vec): vec

Clones this array in the reverse order and returns it, leaving the original array unmodified.

#[test]
fn reversed() {
    let array = [1, 2, 3, 4];
    let reversed = array.reversed();

    assertEq(array, [1, 2, 3, 4]);
    assertEq(reversed, [4, 3, 2, 1]);
}

Array.len(array: vec): int

The length of this array.

#[test]
fn len() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8];
    assertEq(array.len(), 8);
}

Array.empty(array: vec): bool

Is this array empty?

#[test]
fn empty() {
    let array = [];
    assert(array.empty());

    array.push(1);
    assertNot(array.empty());
}

Array.any(array: vec): bool

Does this array have any values (not empty)?

#[test]
fn any() {
    let array = [];
    assertNot(array.any());

    array.push(1);
    assert(array.any());
}

Array.at(array: vec, index: int): unknown

Get a value in this array at a specific index. Will throw an error if the index is out of bounds.

Any value/object that implements an "at" function and a "len" function can be used with for-loops in Stof.

Boxing values inside an array will enable you to manipulate values without setting them.

#[test]
fn at() {
    let array = [1, 2, 3, 4];

    assertEq(array.at(2), 3);
    assertEq(array[3], 4);
}

#[test]
fn nested_at() {
    let array = [[1, 2, 3], [4, 5, 6]];
    assertEq(array[0][1], 2);
    assertEq(array.at(1).at(2), 6);
}

#[test]
fn loops() {
    let vals = [];
    for (i in 0..10) vals.push(i);  // 0..10 is a range array constructor
    assertEq(vals, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
}

Array.first(array: vec): unknown | null

Returns the first value in the array (cloned) or null if the array is empty.

#[test(1)]
fn first(): int {
    let array = [1, 2, 3];
    return array.first();
}

Array.last(array: vec): unknown | null

Returns the last value in the array (cloned) or null if the array is empty.

#[test(3)]
fn last(): int {
    let array = [1, 2, 3];
    return array.last();
}

Array.join(array: vec, separator: str): str

Joins the values inside this array into a singular string, separated by a "separator" value. This array is unmodified.

#[test("hello, world")]
fn join(): str {
    return ["hello", "world"].join(", ");
}

Array.contains(array: vec, value: unknown): bool

Does this array contain a value (equality comparison)?

#[test]
fn contains() {
    let array = ["hello", "world"];
    assert(array.contains("hello"));
    assertNot(array.contains("dne"));
}

Array.find(array: vec, other: unknown): int

Returns the index of the first value in this array to equal "other". If not found, returns -1.

#[test]
fn find() {
    let array = ["hello", "world", 5];
    assertEq(array.find(5), 2);
    assertEq(array.find("world"), 1);
    assertEq(array.find("dne"), -1);
    assertEq(array.find(2), -1);
}

Array.remove(array: vec, other: unknown): unknown | null

Removes the first value in the array to equal "other" and returns it. Returns null if not found.

#[test]
fn remove_first_occurence() {
    let array = ["hello", "world", 5, 4, "world"];
    
    assertEq(array.remove("dne"), null);
    assertEq(array.remove(5), 5);
    assertEq(array.remove("world"), "world");
    assertEq(array, ['hello', 4, 'world']);
}

Array.removeLast(array: vec, other: unknown): unknown | null

Removes the last value in the array to equal "other" and returns it. Returns null if not found.

#[test]
fn remove_last_occurence() {
    let array = ["hello", "world", 4, "world"];
    assertEq(array.removeLast("world"), "world");
    assertEq(array, ["hello", "world", 4]);
}

Array.removeAll(array: vec, other: unknown): vec

Removes all values in the array that equal "other", returning a vector of all values removed.

#[test]
fn remove_all() {
    let array = [1, 1, 1, 1, 2, 1, 1, 1, 1];
    assertEq(array.removeAll(1).len(), 8);
    assertEq(array, [2]);
    assert(array.removeAll(1).empty());
}

Array.insert(array: vec, index: int, ...values: unknown): void

Inserts values into this array at a specific index, shifting existing elements to the right. Must provide at least one value to insert.

Will throw an error if the index is out of bounds or if you do not provide at least one value to insert.

#[test]
fn insert() {
    let array = [1, 2, 3, 4, 5, 6];
    array.insert(2, "hello");
    assertEq(array, [1, 2, 'hello', 3, 4, 5, 6]);
}

Array.set(array: vec, index: int, ...values: unknown): void

Inserts values into this array at a specific index, replacing the existing element at that index. Must provide at least one value to insert.

Will throw an error if the index is out of bounds or if you do not provide at least one value to insert.

#[test]
fn set() {
    let array = [1, 2, 3, 4, 5, 6];
    array.set(2, "hello");
    assertEq(array, [1, 2, "hello", 4, 5, 6]);

    array.set(4, 42);
    assertEq(array, [1, 2, "hello", 4, 42, 6]);
}

Array.iter(array: vec, func: fn): void

Iterates over this array, calling "func" for each value. If "func" returns a non-null value, that value is then set in place of the existing element. The function passed in must take a singular value as a parameter, in the type you know you are iterating over (or "unknown" to accept all).

#[test]
fn iter() {
    let array = 0..15;
    array.iter((val: int): int => {
        if (val % 2 == 0) {
            return val + 1;
        }
        return null; // don't set anything
    });
    assertEq(array, [1, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15]);
}

Array.retain(array: vec, func: fn): void

For each value in this array, call "func" (passing the value in as the only argument) - if "func" returns true, keep the value, otherwise, remove the value from the array.

#[test]
fn retain_evens() {
    let array = 0..100;
    array.retain((v: int): bool => v % 2 == 0);
    assertEq(array, 0..100|2);
}

Array.sort(array: vec, func?: fn): void

Sort this array, optionally providing a function to sort with.

If a function is not provided, Stof will use the "less-than" and "greater-than" built-in functions to compare values.

If providing a function, the function should take two value arguments and return -1 for less than, 1 for greater than, or 0 for equal.

#[test([0, 1, 2, 2, 4, 5, 5, 7, 8])]
fn sort(): vec {
    let array = [5, 2, 4, 5, 7, 8, 0, 2, 1];
    array.sort();
    return array;
}

#[test([2, 3, 5, 6, 6])]
fn sort_by(): vec {
    let array = [new {k:6}, new {k:3}, new {k:5}, new {k:2}, new {k:6}];
    array.sort((a: obj, b: obj): int => {
        if (a.k < b.k) return -1;
        if (a.k > b.k) return 1;
        return 0;
    });
    let res = [];
    for (object in array) {
        res.push(object.k);
    }
    return res;
}
Standard Library