ArrayLib — Array Library

Comprehensive multi-dimensional array support for Plan9Basic. Create dynamic arrays of numbers, strings, or pointers with up to 10 dimensions. Arrays are objects stored as pointers (# suffix) and managed by automatic garbage collection.

FeatureDescription
Indexing1-based (traditional BASIC style)
Dimensions1 to 10 dimensions supported
Data TypesNumeric, String, and Pointer arrays
MemoryAutomatic garbage collection
Bounds CheckingRuntime validation with descriptive errors
Type SafetyRuntime type checking prevents mixing array types
CategoryCountDescription
Creation3dim#, sdim#, pdim# (each with 1–10 dimension overloads)
Access9narr_get/set, sarr_get/set, parr_get/set (via [] syntax)
Utility7ndims, ubound, lbound, arraysize, arraytype, arraytypename$, arr_free
⚠ Warning: Arrays use 1-based indexing. The first element is at index 1, not 0. Accessing index 0 triggers an out-of-bounds error.

Array Types

Plan9Basic supports three distinct array types, each with its own creation function and access syntax.

TypeCreate WithAccess SyntaxInitial Value
Numericdim#(sizes...)arr#[i]0
Stringsdim#(sizes...)arr#$[i]"" (empty)
Pointerpdim#(sizes...)arr##[i]nil
╯ plan9basic
' Numeric array
numbers# = dim#(10)
numbers#[1] = 3.14159
numbers#[2] = -42.5

' String array
names# = sdim#(5)
names#$[1] = "Alice"
names#$[2] = "Bob"

' Pointer array (arrays of arrays, etc.)
objects# = pdim#(3)
objects##[1] = dim#(10)
objects##[2] = sdim#(5)

Array Creation Functions

FunctionSignatureDescription
dim#(s1 [,s2,...,s10])dim#@n...Create numeric array (init to 0)
sdim#(s1 [,s2,...,s10])sdim#@n...Create string array (init to "")
pdim#(s1 [,s2,...,s10])pdim#@n...Create pointer array (init to nil)
╯ plan9basic
' 1D array (vector) with 10 elements
vector# = dim#(10)

' 2D array (matrix) 3x4
matrix# = dim#(3, 4)

' 3D array 2x3x4
cube# = dim#(2, 3, 4)

' String grid
grid# = sdim#(10, 10)

' Table: 100 rows x 3 columns
table# = sdim#(100, 3)

' Jagged array (array of arrays with different sizes)
jagged# = pdim#(3)
jagged##[1] = dim#(10)
jagged##[2] = dim#(20)
jagged##[3] = dim#(5)
ⓘ Note: Each dimension size must be ≥ 1. All creation functions support 1 to 10 dimension parameters.

Array Access Syntax

Plan9Basic uses square brackets [ ] with the appropriate suffix for each array type.

Numeric Arrays

╯ plan9basic
arr# = dim#(5, 5)
arr#[2, 3] = 42           ' Set element at row 2, col 3
value = arr#[2, 3]        ' Read element (value = 42)

String Arrays

╯ plan9basic
names# = sdim#(10)
names#$[3] = "Charlie"    ' Set string at index 3
name$ = names#$[3]        ' Read string

Pointer Arrays

╯ plan9basic
objects# = pdim#(5)
objects##[2] = somePtr#   ' Set pointer at index 2
obj# = objects##[2]       ' Read pointer

Internal Function Mapping

SyntaxInternal CallOperation
arr#[i, j]narr_get(arr#, i, j)Read numeric
arr#[i, j] = vnarr_set#(arr#, i, j, v)Write numeric
arr#$[i]sarr_get$(arr#, i)Read string
arr#$[i] = s$sarr_set#(arr#, i, s$)Write string
arr##[i]parr_get#(arr#, i)Read pointer
arr##[i] = p#parr_set#(arr#, i, p#)Write pointer

Array Utility Functions

FunctionSignatureDescription
ndims(arr#)ndims@#Number of dimensions (1–10)
ubound(arr#, dim)ubound@#nUpper bound (size) of dimension
lbound(arr#, dim)lbound@#nLower bound of dimension (always 1)
arraysize(arr#)arraysize@#Total number of elements (product of dimensions)
arraytype(arr#)arraytype@#Type code: 0=numeric, 1=string, 2=pointer
arraytypename$(arr#)arraytypename$@#Type name: "numeric", "string", "pointer"
arr_free(arr#)arr_free@#Explicitly free an array and remove it from the garbage collector
╯ plan9basic
vector# = dim#(10)
matrix# = dim#(5, 4)
cube# = dim#(2, 3, 4)

println ndims(vector#)         ' 1
println ndims(matrix#)         ' 2
println ndims(cube#)           ' 3

println ubound(matrix#, 1)     ' 5 (rows)
println ubound(matrix#, 2)     ' 4 (columns)
println lbound(matrix#, 1)     ' 1 (always)

println arraysize(vector#)     ' 10
println arraysize(matrix#)     ' 20 (5 x 4)
println arraysize(cube#)       ' 24 (2 x 3 x 4)

println arraytype(vector#)     ' 0 (numeric)
strArr# = sdim#(10)
println arraytypename$(strArr#) ' "string"
ⓘ Note: lbound() always returns 1 in Plan9Basic. It is included for compatibility with traditional BASIC conventions.

Error Handling

ArrayLib performs comprehensive validation with descriptive error messages.

Error TypeExampleMessage
Dimension < 1dim#(0)Dimension 1 must be ≥ 1, got 0
Too many dimsdim#(1,1,...,1) (11+)dim# supports maximum 10 dimensions
Index out of boundsarr#[0] or arr#[6] (size 5)Index 1 out of bounds: 0 (valid: 1..5)
Dimension mismatchmatrix#[1] (2D array)array has 2 dimensions, got 1 indices
Type mismatchstrArr#[1] (read as numeric)Expected numeric array, got string array
Null pointerarr# = 0; arr#[1]Null array pointer
╯ plan9basic
arr# = dim#(5)

' These cause runtime errors:
' arr#[0] = 10     ' ERROR: Index out of bounds: 0 (valid: 1..5)
' arr#[6] = 10     ' ERROR: Index out of bounds: 6 (valid: 1..5)

matrix# = dim#(3, 4)
' value = matrix#[1]     ' ERROR: array has 2 dimensions, got 1 index
' value = matrix#[1,2,3] ' ERROR: array has 2 dimensions, got 3 indices

Complete Examples

Vector Operations

╯ vector.bas
' Create a vector and compute sum of squares
vector# = dim#(10)

for i = 1 to 10
    vector#[i] = i * i
next

println "Squares from 1 to 10:"
for i = 1 to 10
    println i; " squared = "; vector#[i]
next

sum = 0
for i = 1 to ubound(vector#, 1)
    sum = sum + vector#[i]
next
println "Sum of squares: "; sum

Multiplication Table (2D Matrix)

╯ matrix.bas
' 2D matrix multiplication table
rows = 3
cols = 3
matrix# = dim#(rows, cols)

for r = 1 to rows
    for c = 1 to cols
        matrix#[r, c] = r * c
    next
next

println "Multiplication Table:"
for r = 1 to rows
    for c = 1 to cols
        print matrix#[r, c]; " ";
    next
    println ""
next

Name List (String Array)

╯ namelist.bas
' String array with names
names# = sdim#(5)
names#$[1] = "Alice"
names#$[2] = "Bob"
names#$[3] = "Charlie"
names#$[4] = "Diana"
names#$[5] = "Eve"

println "Name List:"
for i = 1 to ubound(names#, 1)
    println i; ". "; names#$[i]
next

Jagged Array (Array of Arrays)

╯ jagged.bas
' Triangle pattern using pointer array
triangle# = pdim#(5)

for row = 1 to 5
    triangle##[row] = dim#(row)
    rowArray# = triangle##[row]
    for col = 1 to row
        rowArray#[col] = row * 10 + col
    next
next

println "Triangle Array:"
for row = 1 to 5
    rowArray# = triangle##[row]
    for col = 1 to ubound(rowArray#, 1)
        print rowArray#[col]; " ";
    next
    println ""
next

Array Inspector Function

╯ inspector.bas
' Display array information
function showArrayInfo(arr#) local d
    println "Array Information:"
    println "  Type: "; arraytypename$(arr#)
    println "  Dimensions: "; ndims(arr#)
    println "  Total elements: "; arraysize(arr#)
    
    println "  Dimension sizes:"
    for d = 1 to ndims(arr#)
        println "    Dim "; d; ": "; lbound(arr#, d); " to "; ubound(arr#, d)
    next
endfunction

numArr# = dim#(10, 20, 30)
showArrayInfo(numArr#)
println ""
strArr# = sdim#(5, 5)
showArrayInfo(strArr#)

3D RGB Color Cube

╯ rgb_cube.bas
' 3D array for RGB image data
width = 10
height = 10
channels = 3

image# = dim#(width, height, channels)

for x = 1 to width
    for y = 1 to height
        image#[x, y, 1] = (x - 1) * 25   ' Red
        image#[x, y, 2] = (y - 1) * 25   ' Green
        image#[x, y, 3] = 128             ' Blue
    next
next

cx = 5
cy = 5
println "Pixel at ("; cx; ","; cy; "):"
println "  R="; image#[cx, cy, 1]
println "  G="; image#[cx, cy, 2]
println "  B="; image#[cx, cy, 3]

Technical Notes

Memory Management

Arrays are automatically managed by Plan9Basic’s garbage collector and are collected when no longer referenced. For long-running scripts that allocate many large arrays, you can also free memory explicitly:

FunctionSignatureDescription
arr_free(arr#)arr_free@#Immediately free the array and remove it from the GC. The pointer becomes invalid after this call.
╯ plan9basic
' Process a large dataset then release memory immediately
buf# = dim#(1000000)
' ... fill and process buf# ...
arr_free(buf#)   ' Freed — do not use buf# after this point
⚠ Warning: Do not access an array after calling arr_free(). The garbage collector will not protect a freed pointer — further use will cause a runtime error.

Performance Tips

TipDetails
Prefer fewer dimensions1–3 dimensions for most use cases; higher dimensions add index calculation overhead
Reuse arraysAvoid creating new arrays repeatedly in loops; reuse existing ones
Manual index calculationFor tight loops, a 1D array with manual indexing can be faster than multi-dimensional

Internal Signatures

FunctionPatternDescription
dim#dim#@n to dim#@nnnnnnnnnnCreate numeric (1–10 dims)
sdim#sdim#@n to sdim#@nnnnnnnnnnCreate string (1–10 dims)
pdim#pdim#@n to pdim#@nnnnnnnnnnCreate pointer (1–10 dims)
narr_get/setnarr_get@#n...Numeric get/set (1–10 indices)
sarr_get$/setsarr_get$@#n...String get/set (1–10 indices)
parr_get#/setparr_get#@#n...Pointer get/set (1–10 indices)
arr_freearr_free@#Explicit memory release

Quick Reference

FunctionSignatureDescription
dim#(sizes...)dim#@n...Create numeric array (init 0)
sdim#(sizes...)sdim#@n...Create string array (init "")
pdim#(sizes...)pdim#@n...Create pointer array (init nil)
arr#[i, j, ...]narr_get@#n...Read numeric element
arr#[i, j, ...] = vnarr_set#@#n...nWrite numeric element
arr#$[i, j, ...]sarr_get$@#n...Read string element
arr#$[i, j, ...] = s$sarr_set#@#n...$Write string element
arr##[i, j, ...]parr_get#@#n...Read pointer element
arr##[i, j, ...] = p#parr_set#@#n...#Write pointer element
ndims(arr#)ndims@#Number of dimensions
ubound(arr#, dim)ubound@#nUpper bound of dimension
lbound(arr#, dim)lbound@#nLower bound (always 1)
arraysize(arr#)arraysize@#Total element count
arraytype(arr#)arraytype@#Type code: 0/1/2
arraytypename$(arr#)arraytypename$@#Type name string
arr_free(arr#)arr_free@#Explicitly free array memory

3 creation functions (with 10 overloads each) + 9 access functions (10 overloads each) + 7 utility functions.