Skip to main content

Documentation Index

Fetch the complete documentation index at: https://soul-lang.com/llms.txt

Use this file to discover all available pages before exploring further.

index

Index access allows you to retrieve and modify elements in arrays, lists, strings, and object properties using square bracket notation []. This is fundamental for working with collections and data structures in Soul.

Array Index Access

Access array elements by their numeric index:
numbers = [10, 20, 30, 40, 50]

// Read elements
first = numbers[0]        // 10
second = numbers[1]       // 20
last = numbers[4]         // 50

// Modify elements
numbers[0] = 100          // [100, 20, 30, 40, 50]
numbers[2] = 300          // [100, 20, 300, 40, 50]

Negative Index Access

Access elements from the end of arrays:
items = ["apple", "banana", "cherry", "date"]

// Negative indices (if supported)
last = items[-1]          // "date"
secondLast = items[-2]    // "cherry"

// Alternative: calculate from length
last = items[items.length() - 1]        // "date"
secondLast = items[items.length() - 2]  // "cherry"

String Index Access

Access individual characters in strings:
text = "Hello"

// Read characters
first = text[0]           // "H"
second = text[1]          // "e"
last = text[4]            // "o"

// Note: String modification may not be supported
// text[0] = "h"          // May not work - strings might be immutable

Object Property Index Access

Access object properties using string keys:
user = {
    "name": "Alice",
    "age": 30,
    "email": "alice@example.com"
}

// Read properties
name = user["name"]       // "Alice"
age = user["age"]         // 30

// Modify properties
user["age"] = 31
user["city"] = "New York"

Dynamic Index Access

Use variables as indices:
data = [100, 200, 300, 400, 500]
key = "name"
user = {"name": "Bob", "age": 25}

// Dynamic array index
index = 2
value = data[index]       // 300

// Dynamic object property
property = user[key]      // "Bob"

// Using expressions as indices
middle = data[data.length() / 2]

Multi-dimensional Arrays

Access nested arrays:
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

// Access nested elements
element = matrix[1][2]    // 6 (row 1, column 2)
row = matrix[0]           // [1, 2, 3]

// Modify nested elements
matrix[2][1] = 80         // Changes 8 to 80

Nested Object Access

Access nested object properties:
user = {
    "profile": {
        "name": "Alice",
        "address": {
            "street": "123 Main St",
            "city": "New York"
        }
    }
}

// Access nested properties
name = user["profile"]["name"]                    // "Alice"
city = user["profile"]["address"]["city"]        // "New York"

// Modify nested properties
user["profile"]["address"]["city"] = "Boston"

Array of Objects Index Access

Access properties of objects in arrays:
users = [
    {"name": "Alice", "age": 25},
    {"name": "Bob", "age": 30},
    {"name": "Charlie", "age": 35}
]

// Access object properties in array
firstUserName = users[0]["name"]      // "Alice"
secondUserAge = users[1]["age"]       // 30

// Modify object properties in array
users[0]["age"] = 26
users[2]["name"] = "Charles"

Index with Expressions

Use complex expressions as indices:
data = [10, 20, 30, 40, 50]

// Arithmetic expressions
middle = data[data.length() / 2]
next = data[currentIndex + 1]

// Function calls as indices
index = findIndex(data, target)
value = data[index]

// Conditional expressions
selectedIndex = isEven ? 0 : 1
selectedValue = data[selectedIndex]

Safe Index Access

Handle index bounds safely:
soul safeGet(array, index) {
    if (index >= 0 && index < array.length()) {
        return array[index]
    }
    return null
}

soul safeSet(array, index, value) {
    if (index >= 0 && index < array.length()) {
        array[index] = value
        return true
    }
    return false
}

// Usage
numbers = [1, 2, 3, 4, 5]
value = safeGet(numbers, 10)    // null (safe)
success = safeSet(numbers, 2, 100)  // true

Index in Loops

Use indices in loop constructs:
items = ["apple", "banana", "cherry"]

// Traditional for loop with index
for (i = 0; i < items.length(); i++) {
    println("Index " + i + ": " + items[i])
}

// For-in loop with index (if supported)
for (index, item in items) {
    println("Index " + index + ": " + item)
}

Index Assignment Patterns

Different ways to assign values using indices:
// Direct assignment
arr[0] = "new value"

// Conditional assignment
if (arr[index] == null) {
    arr[index] = "default"
}

// Assignment with computation
arr[i] = arr[i] + 10

// Assignment from other arrays
arr1[i] = arr2[j]

Index with Error Handling

Handle index access errors:
soul getElement(array, index) {
    try {
        return array[index]
    } catch (error) {
        println("Index access error: " + error)
        return null
    }
}

soul setElement(array, index, value) {
    try {
        array[index] = value
        return true
    } catch (error) {
        println("Index assignment error: " + error)
        return false
    }
}

Index with Object Methods

Use index access with object methods:
data = {
    "items": [1, 2, 3, 4, 5],
    "config": {"debug": true}
}

// Method-like access
firstItem = data["items"][0]
debugMode = data["config"]["debug"]

// Combined with method calls
length = data["items"].length()
uppercased = data["items"][0].toString().toUpperCase()

Index Performance Considerations

Optimize index access:
// Cache array length
items = getItems()
length = items.length()

for (i = 0; i < length; i++) {
    processItem(items[i])
}

// Cache frequently accessed objects
config = getConfig()
debugMode = config["debug"]
logLevel = config["logLevel"]

Index Validation

Validate indices before use:
soul validateIndex(array, index) {
    if (array == null) {
        return false
    }
    
    if (typeof index != "number") {
        return false
    }
    
    return index >= 0 && index < array.length()
}

soul accessWithValidation(array, index) {
    if (validateIndex(array, index)) {
        return array[index]
    }
    
    throw("Invalid index: " + index)
}

Best Practices

  1. Check bounds: Always validate indices before use
  2. Use meaningful names: users[currentIndex] instead of users[i]
  3. Handle errors: Wrap index access in try-catch when needed
  4. Cache lengths: Store array lengths in variables for performance
  5. Use safe access: Create helper functions for safe index operations
// Good - safe index access
soul getUserById(users, userId) {
    for (i = 0; i < users.length(); i++) {
        if (users[i]["id"] == userId) {
            return users[i]
        }
    }
    return null
}

// Better - with validation
soul getUserById(users, userId) {
    if (users == null || users.length() == 0) {
        return null
    }
    
    for (i = 0; i < users.length(); i++) {
        user = users[i]
        if (user != null && user["id"] == userId) {
            return user
        }
    }
    
    return null
}
Index access is fundamental to working with data structures in Soul. Use it carefully with proper bounds checking and error handling to create robust applications.