Optional and Containers Indexes/Keys

In Argentum all standard containers, return optionals (?T) when indexed with x[i]. Therefore, Argentum makes it impossible to access beyond the array bounds or using an invalid key in associative containers.

a = Array(String);

a[0] ? log(_)  // print the starting element of the array if it exists
log(a[0] : "") // print the starting element of the array, or an empty string

It not only helps to prevent OOB errors. It can drive business logic:

// Function gets an element from container and creates one if it's absent.
// It takes a container, a key, and a factory lambda:
fn getOrCreate(m MyMap, key int, factory()@Object) {
    // If element exists, return it.
    // Otherwise, call the lambda,
    // store its result into the container under the key,
    // and return it as its own result
    m[key] : m[key] := factory()

Speaking of indexing operation: x[expressions] is a syntactic sugar for calling the methods getAt | setAt. By defining such methods (with an arbitrary number of parameters of arbitrary types), you turn your class into a multi-dimensional containers.

Let's compare with other languages:

Java, C++ (with T::at), Swift, Go, Rust (with slice[index]) - perform runtime bounds checking and throw exceptions/panics. So resilience in these languages/scenarios require indexInBounds() ? container[index] :... double checks.

Rust slice.get returns optional, i.e. acts exactly as subscript in Argentum but with much heavier syntax:

// x = a[i] : 0;
let x = *a.get(i).unwrap_or(&0);

BTW. Iterators and forEach can reduce the number of subscripts but can't replace them entirely.

Leave a Reply

Your email address will not be published. Required fields are marked *