Iterators

functional helpers for easier block iteration (loops, filtering, mapping, etc)


Functions

Predicates


The Iterators module provides functional programming tools for working with collections. From simple loops to complex transformations, it offers a consistent way to process collections with elegant, expressive code.

Key Concepts

  • Collection iteration with various strategies
  • Functional transformations (map, filter, fold)
  • Collection analysis (every?, some?, enumerate)
  • Consistent behavior across all collection types
  • Support for block-based predicate conditions

Basic Usage

Looping Through Collections

numbers: [1 2 3 4 5]

; basic iteration
loop numbers 'n ->
    print ["Number:" n]
; Number: 1 
; Number: 2 
; Number: 3 
; Number: 4 
; Number: 5 

; with index
loop.with:'i numbers 'n ->
    print ["Item" i ":" n]
; Item 0 : 1 
; Item 1 : 2 
; Item 2 : 3 
; Item 3 : 4 
; Item 4 : 5

; dictionary iteration
user: #[name: "John" age: 30]
loop user [key value]->
    print [key "->" value]
; name -> John 
; age -> 30 

Note
Iterator functions work uniformly with all collection types:

  • Blocks: loop [1 2 3] 'x [...]
  • Dictionaries: loop #[a:1 b:2] [k v] [...]
  • Strings: loop "hello" 'c [...]
  • Ranges: loop 1..5 'x [...]
  • Numbers: loop 3 'i [...] (equivalent to 1..3)

Transforming Collections

numbers: 1..5

; transform each element
doubled: map numbers 'x -> x * 2
print doubled       ; 2 4 6 8 10

; using the => shorthand for simple transformations
squared: map numbers => [& ^ 2]
print squared       ; 1 4 9 16 25

; chaining transformations
result: map numbers 'x ->
    (to :string x) ++ "!"
; ["1!" "2!" "3!" "4!" "5!"]

Filtering Elements

numbers: 1..10

; keep elements matching condition
evens: select numbers 'n -> even? n
print evens         ; 2 4 6 8 10

; remove elements matching condition
noEvens: filter numbers 'n -> even? n
print noEvens       ; 1 3 5 7 9

; shorthand for simple predicates
odds: select numbers => odd?
print odds          ; 1 3 5 7 9

Common Patterns

Testing Collections

numbers: [2 4 6 8]

; check if all elements match
every? numbers => even?             ; => true

; check if any element matches
some? numbers => [& > 10]           ; => false

; count matching elements
enumerate numbers 'x -> x > 5       ; => 3

Collecting and Grouping

data: ["apple" "banana" "apricot" "cherry"]

; group by first letter
byLetter: gather data 'word -> first word
print byLetter  
; [a:[apple apricot] b:[banana] c:[cherry]]

; collect elements while condition is true
ascending: collect [1 2 3 2 4 5] 'x -> 
    x < 4
print ascending     ; 1 2 3 2

Advanced Transformations

; fold (reduce) a collection
sum: fold 1..5 [acc val]->
    acc + val
; 15

; with seed value
sumFrom100: fold.seed:100 1..5 [acc val]->
    acc + val
; 115

; arrange (sort) with custom predicate
users: @[
    #[name: "John"  score: 42]
    #[name: "Alice" score: 28]
    #[name: "Bob"   score: 35]
]

sorted: arrange users 'user -> user\score
print.lines map sorted 'u -> u\name     
; Alice
; Bob
; John

Tip
The arrow operator (=>) is particularly useful with iterators for creating concise, readable code. For example: map nums => [& * 2] instead of map nums 'x -> x * 2

Working with Nested Data

; cluster similar items
temps: [22 22 23 25 25 25 24 24]
clusters: cluster temps 'temp -> temp
; [[22 22] [23] [25 25 25] [24 24]]

; chunk using predicate
data: 1..6
chunks: chunk data => [& < 3]
[1 2] [3 4 5 6] 

; finding matches with collect
numbers: [1 2 3 2 1 4 5 4]
duplicates: collect.after numbers 'x ->
    not? contains? first.n:3 numbers x
; 4 5 4

Pipe-based Transformations

; Sample data: list of orders
orders: @[
    #[id: 1 items: ["book" "pen"] total: 25.50 status: "pending"]
    #[id: 2 items: ["laptop"] total: 999.99 status: "completed"]
    #[id: 3 items: ["phone" "case" "charger"] total: 699.00 status: "pending"]
    #[id: 4 items: ["tablet"] total: 299.99 status: "cancelled"]
]

; Process orders using pipes for better readability
result: orders 
    | select 'order -> order\status = "pending"         ; get pending orders
    | map 'order -> #[                                  ; transform structure
        orderId: order\id
        itemCount: size order\items
        cost: order\total
    ]
    | arrange 'order -> order\cost                      ; sort by cost
    | map 'order -> ~{
        Order #|order\orderId|: |order\itemCount| 
        items @ $|order\cost|
     }

print.lines result    
; Order #1: 2 
; items @ $25.5
; Order #3: 3 
; items @ $699.0

Tip
Using pipes (|) can make complex data transformations more readable by breaking them into clear, sequential steps.