GitHub

Lists

Stable List syntax and operations are stable in Levython 1.0.

Lists are ordered, mutable collections that can hold values of any type. Lists in Levython are dynamically-sized arrays with O(1) amortized append and O(1) random access. They use a capacity doubling strategy for efficient memory management.

Creating Lists#

Create lists with square brackets:

levython
# Empty list
empty <- []

# List of numbers
numbers <- [1, 2, 3, 4, 5]

# List of strings
names <- ["Alice", "Bob", "Carol"]

# Mixed types
mixed <- [42, "hello", true, [1, 2]]

Accessing Elements#

Access elements using zero-based indexing:

levython
colors <- ["red", "green", "blue"]

first <- colors[0]   # "red"
second <- colors[1]  # "green"
third <- colors[2]   # "blue"

say("First color: " + first)

Modifying Lists#

Add elements with append():

levython
fruits <- ["apple", "banana"]

# Add an element
append(fruits, "cherry")
say(str(fruits))  # ["apple", "banana", "cherry"]

# Modify by index
fruits[0] <- "apricot"
say(str(fruits))  # ["apricot", "banana", "cherry"]

Iterating Over Lists#

Use for loops to iterate:

levython
numbers <- [10, 20, 30, 40]

# Iterate by value
for num in numbers {
    say(str(num))
}

# Sum all elements
total <- 0
for n in numbers {
    total <- total + n
}
say("Sum: " + str(total))  # Sum: 100

List Functions#

Function Description Time Complexity Example
len(list) Get list length O(1) len([1,2,3]) โ†’ 3
append(list, item) Add item to end O(1) amortized append(nums, 5)
str(list) Convert to string O(n) str([1,2]) โ†’ "[1, 2]"
sum(list) Sum numeric elements O(n) sum([1,2,3]) โ†’ 6
min(list) Find minimum value O(n) min([3,1,2]) โ†’ 1
max(list) Find maximum value O(n) max([3,1,2]) โ†’ 3
sorted(list) Return new sorted list O(n log n) sorted([3,1,2]) โ†’ [1,2,3]
reversed(list) Return new reversed list O(n) reversed([1,2,3]) โ†’ [3,2,1]
levython
items <- [1, 2, 3]

# Get length
size <- len(items)
say("Size: " + str(size))  # Size: 3

# Build a list
result <- []
for i in range(1, 6) {
    append(result, i * 2)
}
say(str(result))  # [2, 4, 6, 8, 10]

# Aggregation functions
numbers <- [5, 2, 8, 1, 9, 3]
say("Sum: " + str(sum(numbers)))        # Sum: 28
say("Min: " + str(min(numbers)))        # Min: 1
say("Max: " + str(max(numbers)))        # Max: 9
say("Sorted: " + str(sorted(numbers)))  # Sorted: [1, 2, 3, 5, 8, 9]

List Slicing#

Extract sublists using slice notation (coming soon in Levython 1.1):

levython
# Current workaround: Manual slicing
numbers <- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# Extract subset using loop
subset <- []
for i in range(2, 5) {
    append(subset, numbers[i])
}
say(str(subset))  # [2, 3, 4]

Multidimensional Lists#

Lists can contain other lists, creating multidimensional structures:

levython
# 2D matrix (3x3)
matrix <- [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

# Access elements
first_row <- matrix[0]        # [1, 2, 3]
center <- matrix[1][1]        # 5
say("Center element: " + str(center))

# Iterate over 2D list
say("Matrix elements:")
for row in matrix {
    for cell in row {
        say("  " + str(cell))
    }
}

# 3D list (2x2x2)
cube <- [
    [[1, 2], [3, 4]],
    [[5, 6], [7, 8]]
]
element <- cube[0][1][0]  # 3
say("Cube element: " + str(element))

Performance Characteristics#

Levython lists are implemented as dynamic arrays (C++ std::vector internally) with excellent performance characteristics:

Time Complexity

Operation Complexity Notes
Access by index: list[i] O(1) Direct memory access
Append: append(list, x) O(1) amortized Capacity doubling when full
Length: len(list) O(1) Stored as metadata
Iteration O(n) Cache-friendly linear scan
Sort: sorted(list) O(n log n) Optimized quicksort/mergesort

Memory Efficiency

  • NaN-Boxed Values: Each list element is exactly 8 bytes (13x smaller than naive implementations)
  • Capacity Management: Lists automatically resize with 2x growth factor for O(1) amortized append
  • Contiguous Memory: Elements stored sequentially for optimal CPU cache utilization
  • Zero-Copy Iteration: For loops access list elements directly without allocation
Performance: Levython lists are as fast as C++ vectors. Random access is ~1-2ns per element, and iteration throughput exceeds 1GB/s on modern CPUs due to cache-friendly layout and JIT-optimized loops.

Best Practices

levython
# Good: Pre-allocate if size is known (future feature)
# For now, append is already optimized

# Good: Use sorted() instead of manual sorting
numbers <- [5, 2, 8, 1, 9]
sorted_nums <- sorted(numbers)

# Good: Use sum() instead of manual accumulation
total <- sum(numbers)  # Faster than manual loop

# Good: Direct iteration is fastest
for item in list {
    # Process item
}

# Avoid: Repeated concatenation (creates copies)
# Better to use append() which mutates in-place