Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

lib/array.x

Dynamic contiguous arrays of Var elements.

Primary API

FunctionSummary
Array.concatReturns a new Array holding the elements of a followed by those of b.
Array.containsReturns nonzero when some element of array equals value.
Array.copyReturns a new Array holding the same elements as array.
Array.countReturns how many elements compare equal to value.
Array.findReturns the index of the first element equal to value, or -1.
Array.foldlFolds fn over array from seed, front to back.
Array.getindexReturns the element at index, or void when index is out of range.
Array.getsliceReturns a new Array holding the elements array[start:end:step].
Array.indexofReturns Array.find(array, value).
Array.insertInserts elem at index and returns it, or void when out of range.
Array.iterInitializes dest as an iterator over the elements of x.
Array.joinJoins the elements of array into one String separated by separator.
Array.mapReturns a new Array holding func applied to each element of array.
Array.map2Maps func over corresponding elements up to the shorter Array.
Array.newReturns a fresh empty Array with its own identity.
Array.postfixindexApplies postfix Array element increment or decrement.
Array.pushAppends elem to the end of array and returns it.
Array.removeRemoves and returns the element at index, or void when out of range.
Array.resizeResizes arr, truncating or appending Null elements as needed.
Array.reverseReverses array in place and returns that same Array.
Array.setindexStores elem at index and returns it, or void when out of range.
Array.setsliceReplaces the region array[start:end] with the elements of values and returns array.
Array.shiftRemoves and returns the first element of array, or void if it is empty.
Array.sortSorts array in place in ascending order and returns that same Array.
Array.sort_byStably sorts array by keys produced once per value, returning the Array.
Array.sort_withStably sorts array with a borrowed synchronous comparator and returns it.
Array.spliceReplaces remove_count elements at index with values and returns what was removed.
Array.take_lastTakes and returns the last element of array, or void if it is empty.
Array.try_nextWrites the next element, advances cursor, and returns one.
Array.unshiftInserts elem at the front of array and returns it.
Array.updateindexUpdates one Array element in place.
Array.write_strAppends the Array display text to out, using each element’s write_str.
Block.arrayReturns the same object as an Array view; mutations remain shared.
Iter.arrayDrains iter into a fresh Array.

Array

Array.concat

Self Array.concat(Self a, Self b)

Returns a new Array holding the elements of a followed by those of b. Neither input is modified and the result is a fresh object. A null or empty b yields a copy of a.

Raises: <size-limit> or <alloc-fail> when the result cannot be represented or allocated.

Source: lib/array.x:433

Array.contains

int Array.contains(Array array, Var value)

Returns nonzero when some element of array equals value. Uses the same linear search and structural Var equality as Array.find. Use a Map for frequent membership tests.

Raises: <size-limit> when array exceeds the INT_MAX index limit that Array.getindex describes.

Source: lib/array.x:416

Array.copy

Self Array.copy(Self array)

Returns a new Array holding the same elements as array. The copy is shallow and independent: pushing to one does not affect the other, but the two share whatever objects their elements point at. Because Arrays are identity-bearing, plain assignment aliases instead of copying, so copy before handing scratch storage to code that may mutate it.

Raises: <size-limit> or <alloc-fail> when the copy cannot be represented or allocated.

Source: lib/array.x:311

Array.count

int Array.count(Array array, Var value)

Returns how many elements compare equal to value.

Source: lib/array.x:419

Array.find

int Array.find(Array array, Var value)

Returns the index of the first element equal to value, or -1. The scan is linear and compares with Var equality, the same rule == applies to boxed values. Arrays and Maps participate structurally, while === remains the identity test. Array.indexof is a synonym.

Raises: <size-limit> when array exceeds the INT_MAX index limit that Array.getindex describes.

Source: lib/array.x:405

Array.foldl

Var Array.foldl(Array array, Var seed, Func fn)

Folds fn over array from seed, front to back. A void seed means “no seed”: the first element becomes the accumulator and the fold starts at the second, so folding an empty Array that way returns void. Elements are passed as values. Input with nothing left to fold does not invoke or check fn. The callback receives the accumulator then the next element and is not retained. It must not structurally mutate array during the walk. Any cause from Func.apply or fn propagates without changing array.

Source: lib/array.x:498

Array.getindex

Var Array.getindex(Array array, int index)

Returns the element at index, or void when index is out of range. This is what array[index] lowers to. A negative index counts from the end, so -1 is the last element and -array.len() is the first. An index that still falls outside the array after that normalization yields void.

Array has no Array.try_get; the void result reports the miss. It is unambiguous because void is excluded from the element domain. Raw Null is Array data and reads back as itself.

Compound assignment and increment/decrement on an indexed Array become single calls to Array.updateindex and Array.postfixindex. The read, modify, and write happen in one call. That is not thread-safe synchronization.

Array digits = [0, 1, 2, 3, 4, 5];
printf("%s %s\n", digits[0].repr(), digits[-1].repr());
printf("%s %s\n", digits[6].repr(), digits[-7].repr());

Raises: <size-limit> when array holds more than INT_MAX elements.

Source: lib/array.x:128

Array.getslice

Self Array.getslice(Self array, int start, int end, int step)

Returns a new Array holding the elements array[start:end:step]. This is what array[start:end:step] lowers to; a part omitted from that literal form becomes the whole-array default. Negative bounds count from the end and a negative step walks backwards, normalized the same way List and String slicing normalize them, so the rules match across the three types.

The result is a fresh Array, never a view, so later writes to either side are invisible to the other. A range that selects nothing yields an empty Array. Ask for the rest of an array by omitting the bound, as in array[start:]. A forward end above the length is not clamped to it and reads one element beyond the last.

Array digits = [0, 1, 2, 3, 4, 5];
printf("%s %s\n", digits[1:4].repr(), digits[3:].repr());
printf("%s %s\n", digits[::2].repr(), digits[::-1].repr());

Raises: <bad-arg> when step is zero, or <size-limit> when array exceeds the INT_MAX index limit that Array.getindex describes.

Source: lib/array.x:336

Array.indexof

int Array.indexof(Array array, Var value)

Returns Array.find(array, value).

Source: lib/array.x:425

Array.insert

Var Array.insert(Array array, int index, Var elem)

Inserts elem at index and returns it, or void when out of range. Elements at and after index move up one position. An insertion may also land past the last element, so the accepted range is one wider than for reading. index may equal array.len(), which appends.

Negative indices normalize against that wider range, so they do not line up with Array.getindex. -1 appends at the end, -2 inserts before the last element, and -(array.len() + 1) inserts at the front. Anything further out inserts nothing and returns void.

Raises: <void-op> when elem is void and index is in range, or <size-limit> when array exceeds the INT_MAX index limit that Array.getindex describes, or <alloc-fail> when storage cannot grow. These failures leave array unchanged.

Source: lib/array.x:278

Array.iter

Iter Array.iter(Array x, Iter dest)

Initializes dest as an iterator over the elements of x. The caller owns the storage: declare a struct Iter and pass its address. The return value is that same dest, or NULL when dest is null, as in every iterator constructor in the library. foreach (Var item, array) uses this, and the lazy combinators start here.

The iterator borrows x and its stored Var values, so the Array and any pointed-to values used by the caller must remain live. An Iter is single-pass, with no rewind, and any structural mutation of the Array while one is outstanding invalidates it. Iter.array is the other direction, draining an iterator into a fresh Array, and Array.list converts to a canonical List.

Source: lib/array.x:810

Array.join

String Array.join(Array array, String separator)

Joins the elements of array into one String separated by separator. Elements are converted with their str form, so a String element contributes its bytes without quotes and a number contributes its digits. A null separator joins with nothing between elements, and an empty array yields the empty String.

The receiver here is the Array. In String.join the separator is the receiver and the elements arrive as a List. Raises: <alloc-fail> or <size-limit> while rendering or canonicalizing the result, or a cause from an element’s write_str.

Source: lib/array.x:719

Array.map

Array Array.map(Array array, Func func)

Returns a new Array holding func applied to each element of array. array itself is untouched, and elements are passed as values. An empty input returns a fresh empty Array without invoking or checking func. The callback is invoked front to back and is not retained. It must not mutate array while the walk is in progress; Func rejects a void result.

Raises: whatever Func.apply or func raises, or an allocation cause while constructing the result. The partial result is freed.

Source: lib/array.x:459

Array.map2

Array Array.map2(Array a, Array b, Func func)

Maps func over corresponding elements up to the shorter Array. The callback receives left then right, runs front to back, and is not retained. An empty input does not invoke or check it; neither input may be structurally mutated during the walk.

Raises: whatever Func.apply or func raises, or an allocation cause while constructing the result. The partial result is freed.

Source: lib/array.x:476

Array.new

Array Array.new(void)

Returns a fresh empty Array with its own identity. The literal %[] calls this constructor. Test emptiness with Array.len.

Raises: <alloc-fail> if the backing Block cannot be allocated.

Source: lib/array.x:64

Array.postfixindex

Var Array.postfixindex(Array array, int index, Symbol op)

Applies postfix Array element increment or decrement. The returned value is the original element. The slot remains unchanged if the index or operation is invalid.

Raises: <bad-arg> for a null Array or invalid index, <size-limit> when its length cannot be indexed, or any cause from Var.postfix. The element is unchanged on failure.

Source: lib/array.x:188

Array.push

Var Array.push(Array array, Var elem)

Appends elem to the end of array and returns it. Returning the appended value lets a push be used directly in another expression. The array grows as needed; capacity is an implementation detail.

Array queue = [];
queue.push(10);
queue.push("twenty");
printf("%s\n", queue.repr().str());

Raises: <void-op> when elem is void, or <size-limit> when the Array cannot grow within its index domain, or <alloc-fail> when storage cannot grow. These failures leave array unchanged.

Source: lib/array.x:213

Array.remove

Var Array.remove(Array array, int index)

Removes and returns the element at index, or void when out of range. Elements after index move down one position, so this is O(n) unless index is the last one. Negative indices count from the end as in Array.getindex, so -1 removes the last element. Array.insert uses a different rule. An empty array yields void.

Raises: <size-limit> when array exceeds the INT_MAX index limit that Array.getindex describes.

Source: lib/array.x:296

Array.resize

void Array.resize(Array arr, size_t size)

Resizes arr, truncating or appending Null elements as needed.

Raises: <size-limit> when size exceeds the Array index domain, plus any cause from Block growth. Allocation and size failure do not return here. A growth failure leaves the length and existing elements unchanged.

Source: lib/array.x:71

Array.reverse

Self Array.reverse(Self array)

Reverses array in place and returns that same Array. To preserve the original order, slice with a negative step (array[::-1]), which builds a fresh Array.

Source: lib/array.x:448

Array.setindex

Var Array.setindex(Array array, int index, Var elem)

Stores elem at index and returns it, or void when out of range. This is what array[index] = elem lowers to. Negative indices count from the end as in Array.getindex. An out-of-range index changes nothing and is reported by the void result. setindex never grows the array; use Array.push or Array.insert to add an element.

The bounds check runs before the value check, so an out-of-range write of void returns void instead of failing.

Raises: <void-op> when elem is void and index is in range, or <size-limit> when array exceeds the INT_MAX index limit that Array.getindex describes.

Source: lib/array.x:148

Array.setslice

Self Array.setslice(Self array, int start, int end, Self values)

Replaces the region array[start:end] with the elements of values and returns array. The replacement need not match the length of the region it replaces. The array grows or shrinks and the tail moves to fit. A null or empty values deletes the region, and an empty region inserts.

Bounds are normalized exactly as array[start:end] normalizes them, so the replaced region is the one that slice selects: start counts from the end when negative, and a negative end is a stop, with -1 naming the position after the last element. A reversed pair is swapped. There is no step and no bracket spelling; array[start:end] = values is not accepted, so call the method. Aliasing is handled, so passing array as its own values copies first.

Raises: <size-limit> when either Array cannot be indexed or the result cannot be represented, or <alloc-fail> while copying an aliased source or growing. These failures leave array unchanged.

Source: lib/array.x:365

Array.shift

Var Array.shift(Array array)

Removes and returns the first element of array, or void if it is empty. Every remaining element moves down one position, so this is O(n) in the length while Array.take_last is O(1). Pair Array.push with shift for a FIFO queue and with Array.take_last for a stack.

Source: lib/array.x:243

Array.sort

Self Array.sort(Self array)

Sorts array in place in ascending order and returns that same Array. Call Array.copy first to preserve the original order. Ordering is Var.compare, which compares numbers numerically and Strings, Symbols, and Atoms by content. The sort is qsort, so it is not stable, and a null or one-element array is returned unchanged.

Array numbers = [5, 3, 9, 1];
Array sorted = numbers.sort();
printf("%s %d\n", numbers.repr(), sorted == numbers);

Raises: causes from element comparison. The Array may already be partially reordered when a catch receives the cause.

Source: lib/array.x:539

Array.sort_by

Self Array.sort_by(Self array, Func key)

Stably sorts array by keys produced once per value, returning the Array. The borrowed callback runs front to back and must not mutate this Array. Keys use Var.compare; equal keys preserve the original element order. A null or empty Array invokes no callback. Sorting another Array inside the callback is valid. Raises: allocation, key comparison, Func.apply, or callback causes. Failure leaves the original Array unchanged; callback side effects are not undone.

Source: lib/array.x:605

Array.sort_with

Self Array.sort_with(Self array, Func compare)

Stably sorts array with a borrowed synchronous comparator and returns it. The callback receives two values; its result converts to int, with a negative, zero, or positive result ordering the first before, equal to, or after the second. It must give a consistent ordering and must not mutate this Array. Sorting a different Array inside the callback is valid. Null and fewer than two elements return unchanged without a callback.

Raises: allocation, Func.apply, conversion, or callback causes. Failure leaves the original Array unchanged; temporary storage is released. Callback side effects are not undone.

Source: lib/array.x:560

Array.splice

Self Array.splice(Self array, int index, int remove_count, Self values)

Replaces remove_count elements at index with values and returns what was removed. The returned Array is fresh and holds the removed region in order. index is normalized as a slice bound, so a negative value counts from the end and a value past the end clamps to it. A remove_count of zero or less removes nothing, making splice an insertion; a null values makes it a deletion.

Raises: <size-limit> when either Array or the result cannot be represented, or <alloc-fail> while copying or growing. These failures leave array unchanged.

Source: lib/array.x:391

Array.take_last

Var Array.take_last(Array array)

Takes and returns the last element of array, or void if it is empty. With Array.push this makes a stack. Both work at the end of the array, move no other elements, and are amortized O(1). Capacity is retained after taking the element, so taking and pushing again does not reallocate.

Source: lib/array.x:229

Array.try_next

int Array.try_next(Array array, int *cursor, Var *out)

Writes the next element, advances cursor, and returns one. Initialize the caller-owned cursor to zero. A null Array, a null pointer, a negative cursor, or exhaustion returns zero without changing cursor or out. Structural mutation invalidates an outstanding cursor.

foreach (Var item, array) compiles to this loop.

Raises: <size-limit> for an Array outside the integer index domain.

Source: lib/array.x:786

Array.unshift

Var Array.unshift(Array array, Var elem)

Inserts elem at the front of array and returns it. Existing elements move up one position, so this is O(n); Array.push is the amortized O(1) end of the array. Returning elem lets an unshift be used directly in another expression, as Array.push does.

Raises: <void-op> when elem is void, or <size-limit> when the Array cannot grow within its index domain, or <alloc-fail> when storage cannot grow. These failures leave array unchanged.

Source: lib/array.x:256

Array.updateindex

Var Array.updateindex(Array array, int index, Symbol op, Var rhs)

Updates one Array element in place. The index is normalized once, including negative indexing, and the element slot is delegated to Var.update. The stored Var tag is therefore preserved and the slot remains unchanged on failure.

Raises: <bad-arg> for a null Array or invalid index, <size-limit> when its length cannot be indexed, <void-op> for a void right operand, or any cause from Var.update. These failures leave the element unchanged .

Source: lib/array.x:168

Array.write_str

Buffer Array.write_str(Array a, Buffer out)

Appends the Array display text to out, using each element’s write_str. Array.str materializes this into a String.

Source: lib/array.x:741

Block

Block.array

inline Array Block.array(Block x)

Returns the same object as an Array view; mutations remain shared.

Source: lib/array.x:58

Iter

Iter.array

Array Iter.array(Iter iter)

Drains iter into a fresh Array.

Source: lib/array.x:816

Advanced and interop API

FunctionSummary
Array.cleanupEnds the owned lifetime when a managed local leaves its block.
Array.compareCompares Arrays lexicographically with Var.compare.
Array.equalReturns nonzero when two Arrays have structurally equal elements.
Array.heap_popRemoves and returns the smallest element of heap, or void when it is empty.
Array.heap_pushAdds val to heap, an Array maintained as a binary min-heap.
Array.heapifyRearranges heap in place so that it satisfies the min-heap invariant.
Array.remsliceRemoves the region array[start:end] and returns a fresh Array.
Array.reprReturns the readable [ a, b, c ] representation of array.
Array.strReturns an Array display String using each element’s str.
Array.update_nAppends exactly element_count variadic values to array.
Array.write_reprAppends the readable Array representation to out.

Array

Array.cleanup

void Array.cleanup(Array value)

Ends the owned lifetime when a managed local leaves its block.

Source: lib/array.x:824

Array.compare

int Array.compare(Array a, Array b)

Compares Arrays lexicographically with Var.compare.

Source: lib/array.x:518

Array.equal

int Array.equal(Array a, Array b)

Returns nonzero when two Arrays have structurally equal elements.

Source: lib/array.x:732

Array.heap_pop

Var Array.heap_pop(Array heap)

Removes and returns the smallest element of heap, or void when it is empty. The remaining elements are re-heaped in O(log n), so repeated calls yield ascending order and draining a heap is a sort. An Array that never satisfied the heap invariant gives a meaningless answer instead of an error. Call Array.heapify first if it was not built with Array.heap_push.

Raises: any cause reported by element comparison while restoring the heap. The heap may already have removed its root when a catch receives the error.

Source: lib/array.x:685

Array.heap_push

void Array.heap_push(Array heap, Var val)

Adds val to heap, an Array maintained as a binary min-heap. The heap operations arrange an Array as a priority queue in place, with no second data structure and no extra allocation. The elements stay in the Array with the smallest at index 0. Ordering is Var.compare, the same rule Array.sort uses.

heap_push and Array.heap_pop maintain the invariant, but the positional operations do not. After a plain Array.push, an assignment through Array.setindex, or any slicing, call Array.heapify before popping again.

Array heap = [];
heap.heap_push(30);
heap.heap_push(10);
heap.heap_push(20);
printf("%s %s\n", heap.heap_pop().repr(), heap.heap_pop().repr());

Raises: <void-op> when val is void, or <size-limit> when the heap cannot grow within the Array index domain, <alloc-fail> when storage cannot grow, or a cause from element comparison. A value or earlier swap may remain when comparison fails; pre-insertion failures leave the heap unchanged.

Source: lib/array.x:671

Array.heapify

void Array.heapify(Array heap)

Rearranges heap in place so that it satisfies the min-heap invariant. Use this before the first Array.heap_pop on an Array that was built by Array.push, read in from somewhere else, or disturbed by a positional operation. It is O(n), cheaper than pushing the same elements one at a time.

Raises: <size-limit> when heap exceeds the INT_MAX index limit that Array.getindex describes, or a cause from element comparison. Comparison failure may leave a partially rearranged Array.

Source: lib/array.x:704

Array.remslice

Self Array.remslice(Self array, int start, int end)

Removes the region array[start:end] and returns a fresh Array. Bounds are normalized the way that slice normalizes them, so a negative end is a stop. A reversed pair is swapped. Allocation or size failure occurs before array is changed.

Source: lib/array.x:375

Array.repr

String Array.repr(Array array)

Returns the readable [ a, b, c ] representation of array. Each element is rendered with its own repr, so Strings appear quoted and Symbols in angle brackets. The result is for reading and for diagnostics; unlike the List reader syntax it does not round-trip back through a parser. An empty Array renders as [ ].

Array.str has the same shape but uses each element’s str form. Array.write_repr and Array.write_str append to a Buffer instead of allocating a String, and the two String forms are built on them.

Raises: <alloc-fail> or <size-limit> while constructing the result.

Source: lib/array.x:761

Array.str

String Array.str(Array array)

Returns an Array display String using each element’s str.

Source: lib/array.x:744

Array.update_n

Self Array.update_n(Self array, unsigned element_count, ...)

Appends exactly element_count variadic values to array. Values appended before a later <void-op>, <size-limit>, or <alloc-fail> remain in array. The caller must supply that many Var arguments.

Source: lib/array.x:95

Array.write_repr

Buffer Array.write_repr(Array a, Buffer out)

Appends the readable Array representation to out.

Source: lib/array.x:735

Runtime-internal callables

These callables connect runtime translation units. They are documented for source readers but are not supported as user API.

FunctionSummary
Array.blockReturns the same object as a Block view; no copy or transfer occurs.

Array

Array.block

inline Block Array.block(Array x)

Returns the same object as a Block view; no copy or transfer occurs.

Source: lib/array.x:56

Public types

TypeKindSummary
ArrayaliasHolds a mutable identity-bearing sequence of non-void Var elements.

Array

typedef Block Array

Holds a mutable identity-bearing sequence of non-void Var elements. Array is the same object as its Block view; that object and its backing storage belong to the Scope active at construction. Assignment aliases it; Array.copy creates a new container, but still borrows any objects referenced by its elements. Array.free invalidates all aliases.

Source: lib/array.x:35

Design notes

Array is mutable, identity-bearing contiguous Var storage over Block. Every constructor returns an allocated object, including for an empty Array; assignment aliases that object, while Array.copy makes a shallow independent container. Scope owns its allocation unless Array.free shortens the lifetime. Array data may contain raw Null but never void.

The declared Block protocol supplies Array’s generated truth, pop, free, and truncate members. Array.pop discards the final element; Array.take_last removes and returns it.

Indexing and slicing normalize negative positions here. Positional mutation preserves the object identity, and structural mutation invalidates outstanding iterators.

Tests and examples

make verify (unittest/test-array.x) and make examples.