Skip to main content

Lists

Lists are NumFu's primary data structure for working with collections of values. They're immutable, heterogeneous (can contain different types), and come with powerful operations for transformation and manipulation.


Creating Lists

List Literals

Create lists using square brackets with comma-separated elements:

[];                             // Empty list
[1, 2, 3]; // Numbers
["hello", "world"]; // Strings
[true, false, true]; // Booleans
[1, "hello", true]; // Mixed types

Nested Lists

Lists can contain other lists:

[[1, 2], [3, 4]];               // 2D list
[[], [1], [1, 2]]; // Lists of different lengths
[[[1]], [[2, 3]], [[4, 5, 6]]]; // 3D nested structure

Lists with Expressions

List elements can be any expressions:

[1 + 2, 3 * 4, 5^2];            // [3, 12, 25]
[sin(0), cos(0), tan(0)]; // [0, 1, 0]

let x = 10 in [x, x*2, x*3]; // [10, 20, 30]

Accessing List Elements

Indexing

Access elements using square bracket notation (0-based indexing):

let fruits = ["apple", "banana", "cherry"] in
fruits[0]; // "apple"
// or...
fruits[1]; // "banana"
fruits[2]; // "cherry"

Negative Indexing

Access elements from the end using negative indices:

let numbers = [10, 20, 30, 40, 50] in
numbers[-1]; // 50 (last element)
// or...
numbers[-2]; // 40 (second to last)

Nested List Access

Access nested lists by chaining indices:

let matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] in
matrix[1][2]; // 6 (row 1, column 2)
// or...
matrix[0][0]; // 1 (top-left)
matrix[2][2]; // 9 (bottom-right)

Index Bounds

Accessing out-of-bounds indices raises an error:

let short = [1, 2] in
short[5]
// IndexError: List index out of range

List Operations

Concatenation

Combine lists using the + operator:

[1, 2] + [3, 4];                // [1, 2, 3, 4]
["a"] + ["b", "c"] + ["d"]; // ["a", "b", "c", "d"]
[] + [1, 2, 3]; // [1, 2, 3]

Repetition

Repeat lists using the * operator:

[1, 2] * 3;                     // [1, 2, 1, 2, 1, 2]
["hello"] * 2; // ["hello", "hello"]
[1, 2, 3] * 0; // []

List Equality

Compare lists for equality:

[1, 2, 3] == [1, 2, 3];         // true
[1, 2] == [2, 1]; // false (order matters)
[] == []; // true

Built-in List Functions

All of these functions must be imported from the std standard library module. When running the examples below, remember to import it at the top of your file (or in the REPL):

import * from "std"

Length

length([1, 2, 3, 4]);           // 4
length([]); // 0

Adding Elements

[1, 2, 3] + [4]                 // [1, 2, 3, 4]
append([1, 2, 3], 4); // [1, 2, 3, 4]
append([], "first"); // ["first"]

Element Testing

contains([1, 2, 3], 2);           // true
contains(["a", "b", "c"], "x"); // false
contains([[], [1], [2]], []); // true

List Transformation

reverse([1, 2, 3, 4]);          // [4, 3, 2, 1]
reverse([]); // []
reverse(["a", "b", "c"]); // ["c", "b", "a"]

Sorting

sort([3, 1, 4, 1, 5]);                // [1, 1, 3, 4, 5]
sort(["banana", "apple", "cherry"]); // ["apple", "banana", "cherry"]

Slicing

Extract sublists using slice(list, start, end):

slice([1, 2, 3, 4, 5], 1, 3);   // [2, 3, 4] (inclusive end)
slice([1, 2, 3, 4, 5], 0, 2); // [1, 2, 3]
slice([1, 2, 3, 4, 5], 2, -2); // [3, 4] (negative index)

Setting Elements

Create new lists with modified elements:

set([1, 2, 3], 1, 99);          // [1, 99, 3]
set(["a", "b", "c"], 0, "X"); // ["X", "b", "c"]

Functional List Operations

map - Transform Every Element

Apply a function to every element in a list:

let numbers = [1, 2, 3, 4, 5] in
let squares = map(numbers, {x -> x * x}) in
squares // [1, 4, 9, 16, 25]

filter - Select Elements

Keep only elements that satisfy a condition:

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] in
let evens = filter(numbers, {x -> x % 2 == 0}) in
evens // [2, 4, 6, 8, 10]

Examples

When running the examples below, remember to import the std standard library module at the top of your file (or in the REPL) because it provides essential functions for working with lists.

import * from "std"

List Comprehension Style

While NumFu doesn't have list comprehensions, you can simulate them:

// Generate even squares of numbers 1-10
let range = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] in
filter(map(range, {x -> x * x}), {x -> x % 2 == 0})
// [4, 16, 36, 64, 100]

Matrix Operations

Sum each row in a matrix

let matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] in
map(matrix, {row ->
let sum = {lst ->
if length(lst) == 0 then 0
else lst[0] + sum(slice(lst, 1, -1))
} in sum(row)
})
// [6, 15, 24]

Flatten a matrix

let flatten = {lists ->
if length(lists) == 0 then []
else lists[0] + flatten(slice(lists, 1, -1))
} in
flatten([[1, 2], [3, 4], [5, 6]])
// [1, 2, 3, 4, 5, 6]

Transpose a matrix

let transpose = {matrix ->
if length(matrix) == 0 then []
else
let numCols = length(matrix[0]) in
let getColumn = {col ->
map(matrix, {row -> row[col]})
} in
let range = [0, 1, 2] in // Assuming 3x3 matrix
map(range, getColumn)
} in
transpose([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
// [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Statistics

Calculate mean of a list

let mean = {numbers ->
let sum = {lst ->
if length(lst) == 0 then 0
else lst[0] + sum(slice(lst, 1, -1))
} in
sum(numbers) / length(numbers)
} in
mean([10, 20, 30, 40, 50]) // 30

Safe List Access

// Safe indexing with default values
let safeGet = {lst, index, default ->
if index >= 0 && index < length(lst) then lst[index]
else default
};
safeGet([1, 2, 3], 5, 0); // 0 (default)
safeGet([1, 2, 3], 1, 0); // 2 (actual value)

List Validation

// Check if all elements satisfy a condition
let allPositive = {numbers ->
length(filter(numbers, {x -> x > 0})) == length(numbers)
};
allPositive([1, 2, 3, 4]); // true
allPositive([1, -2, 3, 4]); // false

List Reduction

let reduce = {lst, fn, initial ->
if length(lst) == 0 then initial
else reduce(slice(lst, 1, -1), fn, fn(initial, lst[0]))
};
reduce([1, 2, 3, 4], {acc, x -> acc + x}, 0); // 10
reduce([1, 2, 3, 4], {acc, x -> acc * x}, 1); // 24