Tuples
Tuples are ordered, immutable collections of elements that can be of different types. In Harneet, tuples are primarily used for multiple return values from functions.
Overview
Tuples in Harneet: - Immutable - cannot be modified after creation - Heterogeneous - can contain elements of different types - Function returns - primary use case is multiple return values - Destructuring - can be unpacked into multiple variables - Method-rich - built-in .length() and .toArray() methods - Indexable - elements can be accessed by zero-based index
Tuple Creation
Tuples in Harneet are created implicitly by functions that return multiple values:
| Tuple from Function Returns |
|---|
| package main
// Function that returns multiple values (creates a tuple)
function getUserInfo() (string, int, bool) {
return "Alice", 30, true
}
// Tuple is created when not immediately destructured
var userTuple = getUserInfo() // Tuple: ("Alice", 30, true)
|
Tuple Destructuring
The most common way to work with tuples is to destructure them:
| Tuple Destructuring |
|---|
| package main
func getUserInfo() (string, int, bool) {
return "Alice", 30, true
}
// Destructure into individual variables
var name, age, isActive = getUserInfo()
// name = "Alice", age = 30, isActive = true
|
Tuple Instance Methods
length()
Returns the number of elements in the tuple:
| length() |
|---|
| package main
function getCoordinates() (int, int, int) {
return 10, 20, 30
}
var coords = getCoordinates()
var len = coords.length() // 3
|
toArray()
Converts the tuple to an array:
| toArray() |
|---|
| package main
function getValues() (int, string, bool) {
return 42, "hello", true
}
var tuple = getValues()
var arr = tuple.toArray() // [42, "hello", true]
// Now you can use array methods
var arrLen = len(arr) // 3
var first = arr[0] // 42
|
Tuple Indexing
Tuples can be accessed by zero-based index:
| Tuple Indexing |
|---|
| package main
function getColors() (string, string, string) {
return "red", "green", "blue"
}
var colors = getColors()
var first = colors[0] // "red"
var second = colors[1] // "green"
var third = colors[2] // "blue"
|
Common Tuple Patterns
Error Handling
Many functions return tuples with (result, error):
| Error Handling with Tuples |
|---|
| package main
var arr = [1, 2, 3]
// pop() returns (value, error)
var value, err = arr.pop()
if err == None {
fmt.Println("Popped value:", value)
} else {
fmt.Println("Error:", err)
}
// Can also capture the tuple
var result = arr.pop()
var resultLen = result.length() // 2 (value and error)
|
Multiple Return Values
Functions can return any number of values:
| Multiple Return Values |
|---|
| package main
function getDimensions() (int, int, int) {
return 100, 50, 25 // width, height, depth
}
// Destructure
var width, height, depth = getDimensions()
// Or keep as tuple
var dimensions = getDimensions()
var dimArray = dimensions.toArray()
|
None-Receiver Safety
Tuple instance methods enforce None-receiver safety:
| None-Receiver Safety |
|---|
| package main
var t tuple = None
// These will raise runtime errors:
// t.length() // ERROR: type null does not have method 'length'
// t.toArray() // ERROR: type null does not have method 'toArray'
|
Working with Tuple Methods
Converting to Array for Processing
| Convert to Array |
|---|
| package main
func getScores() (int, int, int, int) {
return 95, 87, 92, 88
}
var scoresTuple = getScores()
var scoresArray = scoresTuple.toArray()
// Now use array methods
var total = 0
for score in scoresArray {
total = total + score
}
var average = total / len(scoresArray)
|
Iterating Over Tuple Elements
| Iterate Tuple |
|---|
| package main
func getData() (string, int, bool) {
return "test", 42, true
}
var dataTuple = getData()
var dataArray = dataTuple.toArray()
for i, elem in dataArray {
fmt.Printf("Element %d: %v\n", i, elem)
}
// Output:
// Element 0: test
// Element 1: 42
// Element 2: true
|
Complete Example
| Complete Example |
|---|
| package main
import fmt
// Array methods return tuples for error handling
var numbers = [10, 20, 30, 40, 50]
// pop() returns a tuple (value, error)
var popResult = numbers.pop()
fmt.Println("Pop tuple length:", popResult.length()) // 2
// Destructure the tuple
var poppedValue, popErr = numbers.pop()
if popErr == None {
fmt.Println("Popped:", poppedValue) // 40
}
// shift() also returns a tuple
var shiftResult = numbers.shift()
var shiftArray = shiftResult.toArray()
fmt.Println("Shift result as array:", shiftArray) // [10, None]
// Destructure shift result
var shiftedValue, shiftErr = numbers.shift()
if shiftErr == None {
fmt.Println("Shifted:", shiftedValue) // 20
}
fmt.Println("Remaining array:", numbers) // [30]
|
Use Cases
Safe Array Operations
| Safe Array Operations |
|---|
| package main
var stack = [1, 2, 3]
// Pop with error checking
var value, err = stack.pop()
if err != None {
fmt.Println("Error: stack is empty")
} else {
fmt.Println("Value:", value)
}
|
Multi-Value Configuration
| Multi-Value Configuration |
|---|
| package main
function getServerConfig() (string, int, bool) {
return "localhost", 8080, true
}
var host, port, useSSL = getServerConfig()
fmt.Printf("Server: %s:%d (SSL: %v)\n", host, port, useSSL)
|
Batch Processing Results
| Batch Processing |
|---|
| package main
function processItem(id int) (string, bool, int) {
// Returns (status, success, processingTime)
return "completed", true, 150
}
var results = []
for i = 0; i < 5; i = i + 1 {
var result = processItem(i)
results.push(result)
}
// Process results
for result in results {
var arr = result.toArray()
fmt.Printf("Status: %v, Success: %v, Time: %vms\n",
arr[0], arr[1], arr[2])
}
|
Tuple vs Array
| Feature | Tuple | Array |
| Mutability | Immutable | Mutable |
| Type | Heterogeneous (mixed types) | Can be heterogeneous or typed |
| Creation | Function returns | Literal [...] |
| Indexing | ✅ Zero-based | ✅ Zero-based |
| Methods | .length(), .toArray() | Many instance methods |
| Primary Use | Multiple return values | General collections |
Best Practices
1. Destructure When Possible
| Destructure Tuples |
|---|
| // Preferred: Clear and readable
var name, age, active = getUserInfo()
// Less preferred: Requires indexing
var user = getUserInfo()
var name = user[0]
var age = user[1]
|
2. Use Error Checking Pattern
| Error Checking |
|---|
| // Good: Check error before using value
var value, err = arr.pop()
if err == None {
// Use value safely
fmt.Println(value)
}
// Risky: Ignoring error
var value, _ = arr.pop() // If error, value is None
|
3. Convert to Array for Complex Processing
| Convert for Processing |
|---|
| // When you need array methods or iteration
var tuple = someFunction()
var arr = tuple.toArray()
// Now use array methods
arr.reverse()
arr.slice(0, 2)
|
See Also