Collection Accessors
Some Types expose item access in addition to named properties and methods. Items are not properties: they use the fused collection affixes below. Index or key operands are on DS; with a context selector (t:@(), …) the collection receiver stays on that stack.
| Affix | Effect | Typical types |
|---|---|---|
cs:@() | ( index:i -- value ) | List family, DynamicObject / TypedObject by ordinal; VecNf / Mat2f flat |
cs:!() | ( value index:i -- ) | same; writes an existing slot |
cs:@[] | ( i0:i i1:i … -- value ) | Mat2f: ( r:i c:i -- f ) |
cs:![] | ( value i0:i i1:i … -- ) | Mat2f: ( f r:i c:i -- ) |
cs:@{} | ( key -- value ) | Map family, DynamicObject, TypedObject; missing key errors |
cs:!{} | ( value key -- ) | create or replace |
cs:?{} | ( key -- exists:b ) | Map family, DynamicObject, TypedObject |
help TypeName shows which of @() / !() / @[] / ![] / @{} / !{} / ?{} that type supports. Most types support either the () set or the {} set; DynamicObject and TypedObject support both. Mat2f supports flat () and coordinate [].
Ordinal @() / !()
Zero-based index. !() does not grow a list — use .append^ / .insertAt^ for that.
List.new^ >ts
10 t:.append^
20 t:.append^
30 t:.append^
1 t:@() $ nl // 20
99 1 t:!() // replace index 1
1 t:@() $ nl // 99
t:drop
On DynamicObject / TypedObject, @() / !() use field creation (or declaration) order, not a hash order:
DynamicObject.new^ >ts
1 t:.x!
2 t:.y!
0 t:@() $ nl // 1
t:drop
On Mat2f, @() / !() are flat row-major. Use @[] / ![] for (row, col) — Vectors and Matrices.
Mat @[] / ![]
These accessors take a row/col pair, and return or set the value in that cell.
2 3 Mat2f.new^ >ts
// set row 0, col 2 to a value
1.0 0 2 t:![]
// retrive the value
0 2 t:@[] $ // 1
tdrop
When iterating in nested foreach loops, the following pattern is common:
( mat -- )
>ts
t:.getRowIter^
foreach
t:.getColIter^
foreach
j i t:@[]
// do something with the value
/foreach
/foreach
tdrop
Named @{} / !{} / ?{}
StringMap.new^ >ts
100 "count" t:!{}
"Ada" "name" t:!{}
"name" t:@{} $ nl
"missing" t:?{} $ nl // false
t:drop
@{} on a missing key is an error. Probe first with ?{} (or a type’s hasKey method when provided).
"city" t:?{} if
"city" t:@{} $ nl
else
"n/a" $ nl
then
Prefixed vs bare
Day-to-day code should park the collection and use a selector:
0 t:@()
"k" t:@{}
A bare @() / @{} path whose receiver is on DS (no t: / …) is a one-shot form that elides the receiver after the access. Prefer the rooted cs: form so the handle remains for the next operation.
Chaining after a get
Because @() / @{} leave a value on DS, further member access on that value usually means moving it to a stack first:
"tags" t:@{} >xs
0 x:@() $ nl
x:drop
Or nest through properties when the path stays inside one walk — see Compound Path Syntax.
Collection type APIs (append, clear, iteration, …) are documented under Collection Types.