GoloScript Collections Guide
This comprehensive guide presents all available collections in GoloScript, their methods, and advanced usage patterns like collection comprehensions.
Introduction
GoloScript offers several collection types for different use cases:
- Tuples: Ordered immutable collections
- Arrays: Ordered mutable collections with fast indexing
- Lists: Ordered mutable collections with functional operations (map, filter)
- Vectors: Ordered mutable collections optimized for numeric data
- Sets: Unordered collections with no duplicates
- Maps: Key-value pair collections
★ Insight ─────────────────────────────────────
Immutability vs Mutability: GoloScript clearly distinguishes immutable collections (tuples) from mutable ones (arrays, lists, vectors). Tuples guarantee that once created, their elements cannot be modified, making them perfect for constant data and avoiding bugs related to unexpected modifications.
Collection Choice: Use tuples for unchanging data (coordinates, configurations), arrays for fast index access, lists when you need map/filter, and sets to automatically eliminate duplicates.
─────────────────────────────────────────────────
Collection Types
Literal Syntax
# Tuples - immutable
let tuple = [1, 2, 3]
let emptyTuple = []
# Arrays - mutable
let arr = array[1, 2, 3, 4, 5]
let emptyArray = array[]
# Lists - mutable with functional operations
let list = list[10, 20, 30]
let emptyList = list[]
# Vectors - optimized for numbers
let vec = vector[1.1, 2.2, 3.3]
let emptyVec = vector[]
# Sets - no duplicates
let set = set[1, 2, 3, 2, 1] # Result: set[1, 2, 3]
let emptySet = set[]
# Maps - key-value pairs
let map = map[["name", "Alice"], ["age", 30]]
let emptyMap = map[]
Tuples (immutable)
Tuples are ordered immutable collections. Once created, their elements cannot be modified. All operations return new tuples.
Creation
let tuple1 = [1, 2, 3, 4, 5]
let tuple2 = ["a", "b", "c"]
let emptyTuple = []
let nestedTuple = [[1, 2], [3, 4]]
Available Methods
| Method | Description | Returns | Example |
|---|---|---|---|
size() |
Number of elements | Integer | [1,2,3]: size() → 3 |
length() |
Same as size() | Integer | [1,2,3]: length() → 3 |
get(index) |
Access by index | Element | [10,20,30]: get(1) → 20 |
head() |
First element | Element | [1,2,3]: head() → 1 |
tail() |
All except first | Tuple | [1,2,3]: tail() → [2,3] |
isEmpty() |
Check if empty | Boolean | []: isEmpty() → true |
contains(val) |
Contains element | Boolean | [1,2,3]: contains(2) → true |
indexOf(val) |
Index of element | Integer | ["a","b","c"]: indexOf("b") → 1 |
subTuple(start, end) |
Extract sub-tuple (end inclusive) | Tuple | [0,1,2,3,4]: subTuple(2,4) → [2,3,4] |
extend(...vals) |
Add elements | Tuple (new) | [1,2]: extend(3,4) → [1,2,3,4] |
reverse() |
Reverse order | Tuple (new) | [1,2,3]: reverse() → [3,2,1] |
toArray() |
Convert to array | Array | [1,2,3]: toArray() → array[1,2,3] |
equals(other) |
Equality | Boolean | [1,2]: equals([1,2]) → true |
hashCode() |
Hash code | Integer | [1,2,3]: hashCode() |
compareTo(other) |
Lexicographic comparison | Integer | [1,2,3]: compareTo([1,2,4]) → -1 |
Examples
let fruits = ["apple", "banana", "orange"]
# Element access
println(fruits: get(0)) # apple
println(fruits: head()) # apple
println(fruits: tail()) # [banana, orange]
# Search
println(fruits: contains("banana")) # true
println(fruits: indexOf("orange")) # 2
# Extraction
let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
println(numbers: subTuple(2, 5)) # [2, 3, 4]
# Adding (returns NEW tuple)
let colors = ["red", "green"]
let colors2 = colors: extend("blue", "yellow")
println(colors) # [red, green] (unchanged)
println(colors2) # [red, green, blue, yellow]
# Reversing (returns NEW tuple)
let nums = [1, 2, 3, 4, 5]
let reversed = nums: reverse()
println(nums) # [1, 2, 3, 4, 5] (unchanged)
println(reversed) # [5, 4, 3, 2, 1]
# Method chaining
let result = [5, 4, 3, 2, 1]
: reverse() # [1, 2, 3, 4, 5]
: tail() # [2, 3, 4, 5]
: extend(6, 7) # [2, 3, 4, 5, 6, 7]
Tuple ↔ Array Conversion
# Tuple to Array
let myTuple = [1, 2, 3]
let myArray = myTuple: toArray()
myArray: set(0, 999) # Arrays are mutable
println(myTuple) # [1, 2, 3] (unchanged)
println(myArray) # [999, 2, 3]
# Array to Tuple
let arr = array[10, 20, 30]
let tup = tupleFromArray(arr) # Global function
Arrays (mutable)
Arrays are ordered mutable collections with fast index access.
Creation
let arr = array[1, 2, 3, 4, 5]
let emptyArr = array[]
let strings = array["hello", "world"]
Available Methods
| Method | Description | Returns | Mutates? | Example |
|---|---|---|---|---|
size() |
Number of elements | Integer | No | array[1,2,3]: size() → 3 |
length() |
Same as size() | Integer | No | array[1,2,3]: length() → 3 |
get(index) |
Access by index | Element | No | array[10,20,30]: get(1) → 20 |
set(index, val) |
Modifies element | void | Yes | arr: set(0, 99) |
head() |
First element | Element | No | array[1,2,3]: head() → 1 |
tail() |
All except first | Array | No | array[1,2,3]: tail() → array[2,3] |
isEmpty() |
Check if empty | Boolean | No | array[]: isEmpty() → true |
contains(val) |
Contains element | Boolean | No | array[1,2,3]: contains(2) → true |
indexOf(val) |
Index of element | Integer | No | array["a","b"]: indexOf("b") → 1 |
append(val) |
Add element | Array (new) | No | array[1,2]: append(3) → array[1,2,3] |
reverse() |
Reverse order | Array (new) | No | array[1,2,3]: reverse() → array[3,2,1] |
Examples
# Creation and modification
let numbers = array[1, 2, 3, 4, 5]
# Access
println(numbers: get(0)) # 1
println(numbers: get(2)) # 3
# IN-PLACE modification
numbers: set(2, 99)
println(numbers) # array[1, 2, 99, 4, 5]
# Search
let fruits = array["apple", "banana", "orange"]
println(fruits: contains("banana")) # true
println(fruits: indexOf("orange")) # 2
# Append returns NEW array
let colors = array["red", "green"]
let colors2 = colors: append("blue")
println(colors) # array[red, green] (unchanged)
println(colors2) # array[red, green, blue]
# Chaining
let data = array[5, 4, 3, 2, 1]
let result = data: reverse(): tail(): append(99)
println(result) # array[2, 3, 4, 5, 99]
# Iteration with while
var i = 0
while i < numbers: length() {
println("numbers[" + str(i) + "] =", numbers: get(i))
i = i + 1
}
# Iteration with foreach
foreach num in numbers {
println("Value:", num)
}
Lists (mutable)
Lists are ordered mutable collections with powerful functional operations (map, filter).
Creation
let list = list[1, 2, 3, 4, 5]
let emptyList = list[]
let names = list["Alice", "Bob", "Charlie"]
Available Methods
| Method | Description | Returns | Example |
|---|---|---|---|
size() |
Number of elements | Integer | list[1,2,3]: size() → 3 |
length() |
Same as size() | Integer | list[1,2,3]: length() → 3 |
get(index) |
Access by index | Element | list[10,20,30]: get(1) → 20 |
head() |
First element | Element | list[1,2,3]: head() → 1 |
tail() |
All except first | List | list[1,2,3]: tail() → list[2,3] |
isEmpty() |
Check if empty | Boolean | list[]: isEmpty() → true |
contains(val) |
Contains element | Boolean | list[1,2,3]: contains(2) → true |
indexOf(val) |
Index of element | Integer | list["a","b"]: indexOf("b") → 1 |
append(val) |
Add element | List (new) | list[1,2]: append(3) → list[1,2,3] |
reverse() |
Reverse order | List (new) | list[1,2,3]: reverse() → list[3,2,1] |
map(fn) |
Transform each element | List | list[1,2,3]: map(|x| -> x * 2) |
filter(fn) |
Keep matching elements | List | list[1,2,3,4]: filter(|x| -> x % 2 == 0) |
Map - Transform Each Element
let numbers = list[1, 2, 3, 4, 5]
# Double each number
let doubled = numbers: map(|x| -> x * 2)
println(doubled) # list[2, 4, 6, 8, 10]
# Square each number
let squared = numbers: map(|x| -> x * x)
println(squared) # list[1, 4, 9, 16, 25]
# Transform strings
let names = list["alice", "bob", "charlie"]
let uppercased = names: map(|name| -> name: toUpperCase())
println(uppercased) # list[ALICE, BOB, CHARLIE]
# With formatting
let greetings = names: map(|name| -> "Hello, " + name + "!")
println(greetings) # list[Hello, alice!, Hello, bob!, ...]
Filter - Keep Matching Elements
let allNumbers = list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Keep only even numbers
let evens = allNumbers: filter(|x| -> (x % 2) == 0)
println(evens) # list[2, 4, 6, 8, 10]
# Keep only > 5
let greaterThan5 = allNumbers: filter(|x| -> x > 5)
println(greaterThan5) # list[6, 7, 8, 9, 10]
Chaining Map and Filter
let numbers = list[1, 2, 3, 4, 5]
# Chaining map
let result = numbers
: map(|x| -> x * 2) # Double: [2, 4, 6, 8, 10]
: map(|x| -> x + 1) # +1: [3, 5, 7, 9, 11]
: map(|x| -> x * x) # Square: [9, 25, 49, 81, 121]
println(result)
# Combining filter and map
let data = list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let evenDoubled = data
: filter(|x| -> (x % 2) == 0) # Keep even: [2, 4, 6, 8, 10]
: map(|x| -> x * 2) # Double: [4, 8, 12, 16, 20]
println(evenDoubled)
Practical Example - Temperature Conversion
let celsius = list[0, 10, 20, 30, 40]
# Celsius to Fahrenheit: F = C * 9/5 + 32
let fahrenheit = celsius: map(|c| -> c * 9.0 / 5.0 + 32.0)
println("Celsius:", celsius)
println("Fahrenheit:", fahrenheit)
# Fahrenheit: list[32.0, 50.0, 68.0, 86.0, 104.0]
Using Named Functions
function triple = |x| { return x * 3 }
function isOdd = |x| { return (x % 2) != 0 }
let sample = list[1, 2, 3, 4, 5]
println(sample: map(triple)) # list[3, 6, 9, 12, 15]
println(sample: filter(isOdd)) # list[1, 3, 5]
Vectors
Vectors are ordered mutable collections optimized for numeric data.
Creation
let vec = vector[1.1, 2.2, 3.3]
let integers = vector[100, 200, 300]
let emptyVec = vector[]
Methods
Vectors support the same methods as arrays (get, set, size, etc.).
let vec = vector[1.5, 2.5, 3.5, 4.5]
println(vec: size()) # 4
println(vec: get(0)) # 1.5
vec: set(0, 9.9)
println(vec) # vector[9.9, 2.5, 3.5, 4.5]
Sets
Sets are unordered collections that automatically eliminate duplicates.
Creation
let set1 = set[1, 2, 3, 2, 1] # Result: set[1, 2, 3]
let set2 = set["a", "b", "c"]
let emptySet = set[]
Characteristics
- No duplicates: Duplicate elements are automatically removed
- Unordered: Element order is not guaranteed
- Fast: Constant-time search and insertion
# Duplicates are removed
let numbers = set[1, 2, 3, 2, 1, 3, 4]
println(numbers) # set[1, 2, 3, 4]
# Ideal for eliminating duplicates from a list
let duplicates = list[1, 2, 2, 3, 3, 3, 4]
let unique = set[x foreach x in duplicates]
println(unique) # set[1, 2, 3, 4]
Maps (dictionaries)
Maps are collections of key-value pairs.
Creation
let person = map[["name", "Alice"], ["age", 30], ["city", "Paris"]]
let numbers = map[[1, "one"], [2, "two"], [3, "three"]]
let emptyMap = map[]
Access and Modification
let person = map[["name", "Alice"], ["age", 30]]
# Access via get()
println(person: get("name")) # Alice
println(person: get("age")) # 30
# Check key existence
println(person: containsKey("name")) # true
println(person: containsKey("email")) # false
# Iterate over keys
foreach key in person: keys() {
println(key + ":", person: get(key))
}
Collection Comprehensions
Comprehensions provide a concise syntax for creating collections from other collections.
Basic Syntax
# General syntax
collection[expression foreach variable in source]
# With filter
collection[expression foreach variable in source when condition]
# Nested foreach
collection[expression foreach var1 in source1 foreach var2 in source2]
Simple Examples
# Double each number
let doubles = list[x * 2 foreach x in [1, 2, 3, 4, 5]]
# Result: list[2, 4, 6, 8, 10]
# Keep only even numbers
let evens = list[x foreach x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] when x % 2 == 0]
# Result: list[2, 4, 6, 8, 10]
# With range
let squares = list[x * x foreach x in [1..10]]
# Result: list[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Comprehensions with Ranges
# Range: [start..end] (end inclusive)
let range = [1..5] # [1, 2, 3, 4, 5]
# Usage in comprehension
let squares = list[x * x foreach x in [1..10]]
println(squares)
# list[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Multiple Conditions (multiple when)
# Multiple conditions
let filtered = list[x foreach x in [1..20] when x % 2 == 0 when x > 10]
# Result: list[12, 14, 16, 18, 20]
# (Even AND > 10)
Nested foreach (Cartesian Product)
# Cartesian product
let sums = list[x + y foreach x in [1, 2, 3] foreach y in [10, 20, 30]]
# Result: list[11, 21, 31, 12, 22, 32, 13, 23, 33]
# Create coordinates
let coords = list[[x, y] foreach x in [1..3] foreach y in [1..3]]
# Result: [[1,1], [1,2], [1,3], [2,1], [2,2], [2,3], [3,1], [3,2], [3,3]]
# With filter
let filteredCoords = list[[x, y] foreach x in [1..5] foreach y in [1..5] when x < y]
# Result: Only pairs where x < y
Set Comprehensions
# Set automatically eliminates duplicates
let remainders = set[x % 5 foreach x in [1..20]]
# Result: set[1, 2, 3, 4, 0]
# (Only unique remainder values from division by 5)
String Iteration
# Iterate over string characters
let chars = list[c foreach c in "GOLO"]
# Result: list[G, O, L, O]
# Transform characters
let excited = list[c + "!" foreach c in "abc"]
# Result: list[a!, b!, c!]
Advanced Comprehensions
Tuple Destructuring
# Destructuring: extract elements from tuples
let couples = [[1, 10], [2, 20], [3, 30], [4, 40]]
let sums = list[a + b foreach a, b in couples]
# Result: list[11, 22, 33, 44]
let pairs = [[2, 5], [3, 4], [10, 10]]
let products = list[a * b foreach a, b in pairs]
# Result: list[10, 12, 100]
String Formatting
let numbers = [1, 2, 3, 4, 5]
let formatted = list["Number: " + str(x) foreach x in numbers]
# Result: list[Number: 1, Number: 2, Number: 3, Number: 4, Number: 5]
Finding Pythagorean Triples
# Find all triples (a, b, c) where a² + b² = c²
let pythag = list[
[a, b, c]
foreach a in [1..10]
foreach b in [a..10]
foreach c in [b..10]
when a * a + b * b == c * c
]
# Result: [[3, 4, 5], [6, 8, 10]]
Cartesian Product with Strings
let combinations = list[
letter + digit
foreach letter in ["A", "B", "C"]
foreach digit in ["1", "2", "3"]
]
# Result: list[A1, A2, A3, B1, B2, B3, C1, C2, C3]
Prime Numbers
function isPrime = |n| {
if n < 2 { return false }
var i = 2
while i * i <= n {
if n % i == 0 { return false }
i = i + 1
}
return true
}
let primes = list[x foreach x in [1..50] when isPrime(x)]
# Result: list[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
Functional Operations
Map, Filter, and Reduce
# Map: transform each element
let numbers = list[1, 2, 3, 4, 5]
let doubled = numbers: map(|x| -> x * 2)
# Filter: keep matching elements
let evens = numbers: filter(|x| -> x % 2 == 0)
# Chaining
let result = numbers
: filter(|x| -> x > 2)
: map(|x| -> x * 10)
Map vs Comprehension Comparison
# With map()
let result1 = list[1, 2, 3, 4, 5]: map(|x| -> x * 2)
# With comprehension
let result2 = list[x * 2 foreach x in [1, 2, 3, 4, 5]]
# Both produce: list[2, 4, 6, 8, 10]
Patterns and Best Practices
Choosing the Right Collection
| Use Case | Recommended Collection | Reason |
|---|---|---|
| Constant data | Tuple | Guaranteed immutability |
| Fast index access | Array | Optimal performance |
| Functional transformations | List | Supports map/filter |
| Numeric data | Vector | Optimized for numbers |
| Eliminate duplicates | Set | Automatic |
| Key-value pairs | Map | Appropriate structure |
Immutability
# Tuples are immutable
let tuple = [1, 2, 3]
let newTuple = tuple: extend(4, 5)
# tuple remains [1, 2, 3]
# newTuple is [1, 2, 3, 4, 5]
# Arrays are mutable
let arr = array[1, 2, 3]
arr: set(0, 99)
# arr is now array[99, 2, 3]
Performance
- Tuples: Fast creation, no extra memory allocation for operations
- Arrays: O(1) index access
- Lists: Optimized for map/filter, but requires iteration
- Sets: O(1) average search and insertion
- Maps: O(1) average lookup
Method Chaining
# Readable and expressive
let result = data
: filter(|x| -> x > 0)
: map(|x| -> x * 2)
: filter(|x| -> x < 100)
: reverse()
Complete Examples
FizzBuzz with Comprehensions
# Find all numbers divisible by both 3 AND 5
let fizzbuzz = list[x foreach x in [1..100] when x % 3 == 0 when x % 5 == 0]
println(fizzbuzz) # list[15, 30, 45, 60, 75, 90]
Data Transformation Pipeline
let prices = list[10.0, 20.5, 15.75, 30.0, 5.0]
# Apply 20% discount to prices > 10€
let discounted = prices
: filter(|p| -> p > 10.0)
: map(|p| -> p * 0.8)
println(discounted)
# list[16.4, 12.6, 24.0]
String Manipulation
let names = list["alice", "bob", "charlie"]
let greetings = names
: map(|name| -> name: toUpperCase())
: map(|name| -> "Hello, " + name + "!")
foreach greeting in greetings {
println(greeting)
}
# Hello, ALICE!
# Hello, BOB!
# Hello, CHARLIE!