N

Nanyx

Documentation

Collections

Nanyx provides powerful collection types for working with sequences of data. The primary collection type is the list, which is immutable and efficiently supports functional operations.

Lists

Lists are immutable sequences of values:

-- List creation
def numbers = [1, 2, 3, 4, 5]
def names = ["Alice", "Bob", "Charlie"]
def empty = []

List Type

Lists have a generic type list(a):

def numbers: list(int) = [1, 2, 3]
def names: list(string) = ["Alice", "Bob"]

List Operations

Map

Transform each element:

def doubled = [1, 2, 3] \map { * 2 }
-- Result: [2, 4, 6]

def names = users \map { .name }

Filter

Keep elements that match a predicate:

def evens = [1, 2, 3, 4, 5] \filter { n -> n % 2 == 0 }
-- Result: [2, 4]

def adults = users \filter { .age >= 18 }

Fold

Reduce a list to a single value:

def sum = [1, 2, 3, 4] \fold(0) { + }
-- Result: 10

def product = [1, 2, 3, 4] \fold(1) { * }
-- Result: 24

List Destructuring

Pattern match on lists:

-- Head and tail
rec sumList: list(int) -> int = {
  | [] -> 0
  | [head, ...tail] -> head + sumList(tail)
}

-- Multiple elements
def process = {
  | [] -> "empty"
  | [x] -> "one element"
  | [x, y] -> "two elements"
  | [x, y, ...rest] -> "many elements"
}

List Construction

Build lists with spread syntax:

-- Prepend elements
def newList = [1, 2, ...oldList]

-- Append (less efficient)
def extended = [...list1, ...list2]

-- In pattern matching
rec map: (list(a), (a -> b)) -> list(b) = {
  | [], _ -> []
  | [head, ...tail], f -> [f(head), ...map(tail, f)]
}

Common List Functions

Length

rec length: list(a) -> int = {
  | [] -> 0
  | [_, ...tail] -> 1 + length(tail)
}

Reverse

def reverse: list(a) -> list(a) = { xs ->
  xs \fold([]) { acc, x -> [x, ...acc] }
}

Take

rec take: (list(a), int) -> list(a) = {
  | [], _
  | _, { <= 0 } -> []
  | [head, ...tail], n -> [head, ...take(tail, n - 1)]
}

Drop

rec drop: (list(a), int) -> list(a) = {
  | [], _
  | xs, { <= 0 } -> xs
  | [_, ...tail], n -> drop(tail, n - 1)
}

Ranges

Create numeric sequences:

def oneToTen = [1..10]
-- Result: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def evens = [2, ...4..20]
-- Result: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

List Comprehensions

Build lists declaratively:

-- Simple comprehension
def squares = [for 1..10 | x -> x * x ]

-- With filter
def evenSquares = [for 1..10 | x if x % 2 == 0 -> yield! x * x 
                             | _ -> ()]

-- Zipped generators
def pairs = [for (1..3), (1..3) | x, y -> (x, y)]

Other Collection Types

Maps

Key-value collections:

def ages = dict {
  "Alice" => 30
  "Bob" => 25
  "Charlie" => 35
}

def aliceAge = ages["Alice"]  -- #some(30)
def unknownAge = ages["Unknown"]  -- #none

Sets

Unique value collections:

def numbers = set [1, 2, 3, 2, 1]
-- Result: set [1, 2, 3]

def union = set1 \union set2
def intersection = set1 \intersect set2

Sequences and Lazy Evaluation

For large or infinite collections, use sequences:

-- Infinite sequence
def naturals = Seq.unfold(0) { + 1 }

-- Take first 10
def firstTen = naturals \take(10) \toList

Practical Examples

Finding Elements

rec find: (list(a), (a -> bool)) -> Option(a) = {
  | [] -> #none
  | [head, ...] if predicate(head) ->
  | [_, ...tail] -> find(tail, predicate)
}

def firstEven = [1, 3, 4, 5] \find { % 2 == 0 }
-- Result: #some(4)

Grouping

def groupBy: (list(a), (a -> b)) -> Map(b, list(a)) = { xs, keyFn ->
  xs \fold(dict {}) { acc, x ->
    def key = keyFn(x)
    def existing = acc[key] \getOrElse([])
    acc \insert(key, [x, ...existing])
  }
}

def byAge = users \groupBy { .age }

Sorting

def sort: list(a) -> list(a) = {
  | [] -> []
  | [pivot, ...rest] ->
      def smaller = rest \filter { <= pivot }
      def larger = rest \filter { > pivot }
      [...sort(smaller), pivot, ...sort(larger)]
}