Skip to content
AgileLogics
5 min read

Lists

Prerequisites: for loops and ranges

List is Scala's classic immutable, ordered collection.

@main def lists(): Unit =
  val fruits = List("apple", "banana", "cherry")
  println(fruits.head)
  println(fruits.tail)
  println(fruits(1))
  println(fruits.length)
  println(fruits.last)
  println(fruits.contains("banana"))
  println(fruits.reverse)
apple
List(banana, cherry)
banana
3
cherry
true
List(cherry, banana, apple)
  • head is the first element; tail is everything after it.
  • fruits(1) reads by index, starting from 0 — but indexing a List is slow for large lists (see Vectors).

"Changing" a list creates a new one

@main def immutableLists(): Unit =
  val fruits = List("apple", "banana")
  val more = "kiwi" :: fruits
  val evenMore = more :+ "mango"
  val combined = fruits ++ List("fig", "plum")

  println(fruits)
  println(more)
  println(evenMore)
  println(combined)
  println(fruits.updated(0, "apricot"))
List(apple, banana)
List(kiwi, apple, banana)
List(kiwi, apple, banana, mango)
List(apple, banana, fig, plum)
List(apricot, banana)
  • x :: list adds to the front (fast); list :+ x adds to the end (slower for List); ++ joins two lists.
  • The original fruits never changes. Each operation returns a new list — which sounds wasteful, but the new list shares the unchanged parts with the old one.

Immutable collections are the default in Scala. They can be shared freely — between methods or threads — without anyone changing them under you.

Empty lists and Nil

@main def emptyLists(): Unit =
  val empty = List.empty[Int]
  println(empty.isEmpty)
  println(empty == Nil)
  println(1 :: 2 :: 3 :: Nil)
  println(empty.headOption)
true
true
List(1, 2, 3)
None

Nil is the empty list. head on an empty list throws an error; headOption returns None instead (see the Option lesson).