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.
| Feature | Description |
|---|---|
| Indexing | 1-based (traditional BASIC style) |
| Dimensions | 1 to 10 dimensions supported |
| Data Types | Numeric, String, and Pointer arrays |
| Memory | Automatic garbage collection |
| Bounds Checking | Runtime validation with descriptive errors |
| Type Safety | Runtime type checking prevents mixing array types |
| Category | Count | Description |
|---|---|---|
| Creation | 3 | dim#, sdim#, pdim# (each with 1–10 dimension overloads) |
| Access | 9 | narr_get/set, sarr_get/set, parr_get/set (via [] syntax) |
| Utility | 7 | ndims, ubound, lbound, arraysize, arraytype, arraytypename$, arr_free |
Array Types
Plan9Basic supports three distinct array types, each with its own creation function and access syntax.
| Type | Create With | Access Syntax | Initial Value |
|---|---|---|---|
| Numeric | dim#(sizes...) | arr#[i] | 0 |
| String | sdim#(sizes...) | arr#$[i] | "" (empty) |
| Pointer | pdim#(sizes...) | arr##[i] | nil |
' 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
| Function | Signature | Description |
|---|---|---|
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) |
' 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)
Array Access Syntax
Plan9Basic uses square brackets [ ] with the appropriate suffix for each array type.
Numeric Arrays
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
names# = sdim#(10) names#$[3] = "Charlie" ' Set string at index 3 name$ = names#$[3] ' Read string
Pointer Arrays
objects# = pdim#(5) objects##[2] = somePtr# ' Set pointer at index 2 obj# = objects##[2] ' Read pointer
Internal Function Mapping
| Syntax | Internal Call | Operation |
|---|---|---|
arr#[i, j] | narr_get(arr#, i, j) | Read numeric |
arr#[i, j] = v | narr_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
| Function | Signature | Description |
|---|---|---|
ndims(arr#) | ndims@# | Number of dimensions (1–10) |
ubound(arr#, dim) | ubound@#n | Upper bound (size) of dimension |
lbound(arr#, dim) | lbound@#n | Lower 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 |
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"
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 Type | Example | Message |
|---|---|---|
| Dimension < 1 | dim#(0) | Dimension 1 must be ≥ 1, got 0 |
| Too many dims | dim#(1,1,...,1) (11+) | dim# supports maximum 10 dimensions |
| Index out of bounds | arr#[0] or arr#[6] (size 5) | Index 1 out of bounds: 0 (valid: 1..5) |
| Dimension mismatch | matrix#[1] (2D array) | array has 2 dimensions, got 1 indices |
| Type mismatch | strArr#[1] (read as numeric) | Expected numeric array, got string array |
| Null pointer | arr# = 0; arr#[1] | Null array pointer |
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
' 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)
' 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)
' 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)
' 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
' 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
' 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:
| Function | Signature | Description |
|---|---|---|
arr_free(arr#) | arr_free@# | Immediately free the array and remove it from the GC. The pointer becomes invalid after this call. |
' 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
arr_free(). The garbage collector will not protect a freed pointer — further use will cause a runtime error.Performance Tips
| Tip | Details |
|---|---|
| Prefer fewer dimensions | 1–3 dimensions for most use cases; higher dimensions add index calculation overhead |
| Reuse arrays | Avoid creating new arrays repeatedly in loops; reuse existing ones |
| Manual index calculation | For tight loops, a 1D array with manual indexing can be faster than multi-dimensional |
Internal Signatures
| Function | Pattern | Description |
|---|---|---|
dim# | dim#@n to dim#@nnnnnnnnnn | Create numeric (1–10 dims) |
sdim# | sdim#@n to sdim#@nnnnnnnnnn | Create string (1–10 dims) |
pdim# | pdim#@n to pdim#@nnnnnnnnnn | Create pointer (1–10 dims) |
narr_get/set | narr_get@#n... | Numeric get/set (1–10 indices) |
sarr_get$/set | sarr_get$@#n... | String get/set (1–10 indices) |
parr_get#/set | parr_get#@#n... | Pointer get/set (1–10 indices) |
arr_free | arr_free@# | Explicit memory release |
Quick Reference
| Function | Signature | Description |
|---|---|---|
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, ...] = v | narr_set#@#n...n | Write 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@#n | Upper bound of dimension |
lbound(arr#, dim) | lbound@#n | Lower 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.