1. forall
Executes a procedure for each element of an array, packed array, dictionary, or string.
1.1. Syntax
array proc forall → – packedarray proc forall → – dict proc forall → – string proc forall → –
1.2. Stack Effects
| Level | Object |
|---|---|
1 |
Composite object (array, packed array, dict, or string) |
0 |
|
| Level | Object |
|---|---|
(varies) |
Results from procedure executions |
1.3. Description
forall enumerates elements of the first operand, executing proc for each:
-
Arrays/packed arrays: Pushes each element and executes proc
-
Strings: Pushes each character code (0-255) and executes proc
-
Dictionaries: Pushes each key-value pair and executes proc
For arrays and strings, elements are processed in index order (0 to n-1). For dictionaries, the order is arbitrary.
If the composite object is empty (length 0), forall does not execute proc at all.
1.5. Examples
0 [13 29 3 -8 21] { add } forall
% Result: 58
(abc) { = } forall
% Prints: 97, 98, 99
/d 2 dict def
d /abc 123 put
d /xyz (test) put
d { } forall
% Stack: /xyz (test) /abc 123 (order varies)
[1 2 3 4] { 10 mul } forall
% Stack: 10 20 30 40
1.6. Common Use Cases
1.6.1. Array Processing
% Sum array elements
0 exch { add } forall
% Count elements
0 exch { pop 1 add } forall
% Find maximum
-999999 exch { max } forall
1.7. Common Pitfalls
| Procedure Must Handle Stack - Each element (or key-value pair) is left on the stack for proc to process. |
[1 2 3] { } forall % Leaves 1 2 3 on stack
[1 2 3] { pop } forall % Removes all elements
| Dictionary Order is Arbitrary - Dictionaries enumerate in unpredictable order. |
mydict { } forall % Order not guaranteed
Modifying During Iteration - Adding/removing dictionary entries during forall may or may not affect iteration.
|
Use exit for Early Termination - Execute [exit] within proc to stop iteration.
|
[1 2 3 4 5] {
dup 3 eq { exit } if
} forall % Stops at 3
1.8. Error Conditions
| Error | Condition |
|---|---|
[ |
Object has no-access attribute |
[ |
Procedure pushes too many objects |
[ |
Fewer than 2 operands on stack |
[ |
First operand wrong type, or second not procedure |
1.9. Implementation Notes
-
Elements are processed in place (not copied to stack first)
-
For dictionaries, each iteration pushes key then value
-
New dictionary entries during iteration may or may not be processed
-
For strings, each element is a new integer object (0-255)
1.10. Performance Considerations
-
More efficient than manual iteration with loops
-
Minimal overhead per element
-
For large collections, most efficient iteration method
-
Procedure call overhead is small
1.11. Comparison with Loops
% Using forall
[1 2 3 4] { 10 mul } forall
% Using for loop
0 1 3 {
[1 2 3 4] exch get 10 mul
} for
forall is simpler and more efficient.