Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Lists

Lists in Acton are ordered mutable sequences, similar to a to-do list where items have a specific order. Lists can only contain values of one type at a time due to Acton's static type system.

Think of a list like a row of boxes, where each box can hold one item. All boxes must hold the same type of thing - you can't mix apples and hammers!

Creating Lists

Create a list with initial values
fruits = ["apple", "banana", "orange"]
Create an empty list - type will be inferred when you add the first item
numbers = []

Lists in Acton are implemented as dynamic arrays with amortized O(1) append operations. The underlying storage grows geometrically to maintain performance characteristics.

Basic Operations

Create a list and add items
l = ["foo", "foo"]
l.append("bar")
l.insert(0, "Firsty")
l.append("banana")
Access items by index (counting starts at 0)
# Indexing starts at 0
print("First item: " + l[0])          # First item: Firsty
# Negative index counts from the end
print("Last item : " + l[-1])         # Last item : banana
Print the entire list - must convert to string first
# Note: explicitly cast list to str before printing
print("List items: " + str(l))
# List items: ['Firsty', 'foo', 'foo', 'bar', 'banana']
Get a slice of the list
# [start:stop] where start is inclusive, stop is exclusive
print("A slice   : " + str(l[2:4]))
# A slice   : ['foo', 'bar']

Common mistake: Remember that indexing starts at 0, not 1! So the first item is at position 0, the second at position 1, and so on.

Slicing: The slice l[start:stop] includes the item at start but excludes the item at stop. This is the same behavior as Python.

Modifying Lists

Add items to the end - O(1) amortized time
l.append("new item")
Insert at a specific position - O(n) time complexity
l.insert(0, "first")  # 0 = first position
Remove and return an item
print("Pop first item:", l.pop(0))    # Pop first item: Firsty
print("Pop last item:", l.pop(-1))    # Pop last item: banana
print("List items:", str(l))          # List items: ['foo', 'foo', 'bar']
Extend a list with another list
l.extend(["apple", "orange"])
print("List items:", str(l))
# List items: ['foo', 'foo', 'bar', 'apple', 'orange']

List Utilities

Sort a list (returns a new list)
unsorted_list = [9, 5, 123, 14, 1]
sl = sorted(unsorted_list)
print("Sorted list", str(sl))         # Sorted list [1, 5, 9, 14, 123]
Reverse a list in-place
l.reverse()
print("Reversed:", l)
# Reversed: ['orange', 'apple', 'bar', 'foo', 'foo']
Copy a list - creates a shallow copy
l2 = l.copy()
print("Copy:", l2)
# Copy: ['orange', 'apple', 'bar', 'foo', 'foo']
Clear all items from a list
l.clear()
print("List after clear:", str(l))    # List after clear: []

env.exit(0)

Performance characteristics:

  • append() - O(1) amortized (may occasionally resize)
  • insert() - O(n) as elements need to be shifted
  • pop() - O(1) for last element, O(n) for arbitrary index
  • extend() - O(k) where k is the length of the added list
  • reverse() - O(n) in-place operation
  • copy() - O(n) creates new list

List Comprehensions

List comprehensions provide a concise way to create lists based on existing sequences or ranges. They're like a recipe for making a new list from an existing one!

List comprehensions might look complex at first, but they follow a simple pattern: [expression for item in sequence] - "give me expression for each item in sequence"

Create a list of squares (multiply each number by itself)
squares = [x * x for x in range(5)]
# Result: [0, 1, 4, 9, 16]
Filter with a condition
evens = [x for x in range(10) if x % 2 == 0]
# Result: [0, 2, 4, 6, 8]
Multiple iterators (cartesian product)
pairs = [(x, y) for x in range(3) for y in range(2)]
# Result: [(0,0), (0,1), (1,0), (1,1), (2,0), (2,1)]

Advanced Comprehensions

Nested list comprehension
matrix = [[i * j for i in range(4)] for j in range(3)]
print("Matrix:")
for row in matrix:
    print("  ", row)
# Matrix:
#    [0, 0, 0, 0]
#    [0, 1, 2, 3]
#    [0, 2, 4, 6]
Transform existing list
words = ["hello", "world", "acton"]
lengths = [len(w) for w in words]
print("Word lengths:", lengths)        # Word lengths: [5, 5, 5]
Filter and transform
long_caps = [w.upper() for w in words if len(w) > 4]
print("Long words in caps:", long_caps)
# Long words in caps: ['HELLO', 'WORLD', 'ACTON']

Performance tip: When using multiple iterators with filtering, place filters as early as possible:

# Good - filters early, reduces iterations
result = [x + y for x in big_list if condition(x) for y in small_list]

# Bad - filters late, wastes computation
result = [x + y for x in big_list for y in small_list if condition(x)]

Type Safety

All items in a list must be of the same type. Mixing types like ["foo", 1] will result in a compiler error.

Valid: homogeneous list
strings = ["foo", "bar", "baz"]
numbers = [1, 2, 3, 4, 5]
Invalid: mixed types
# This will not compile!
mixed = ["foo", 1, True]