Day 02 Core Concepts

Functional Collections & Higher-Order Functions

Scala's collection library is the most powerful in any language. Immutable by default, it provides map, filter, flatMap, fold, and dozens more operations that transform data without mutation. Today you master the collection API.

~1 hour Hands-on Precision AI Academy

Today’s Objective

Scala's collection library is the most powerful in any language. Immutable by default, it provides map, filter, flatMap, fold, and dozens more operations that transform data without mutation. Today you master the collection API.

Scala's default collections are immutable: List (linked list), Vector (indexed, fast random access), Set (unique elements), Map (key-value). All operations return new collections — the original is unchanged. Mutable collections (scala.collection.mutable) exist but are used sparingly. Vector is the general-purpose default: O(1) amortized for append, prepend, and random access via 32-way tree structure.

map, flatMap, and for-comprehensions

map transforms each element. filter keeps matching elements. flatMap maps then flattens — essential for working with Option, Either, and nested collections. For-comprehensions are syntactic sugar for map/flatMap/filter: 'for { x <- xs; y <- ys if x != y } yield (x, y)'. For-comprehensions work on any Monad: List, Option, Future, Either.

fold, reduce, and groupBy

foldLeft(initial)(op) reduces left-to-right with an accumulator. foldRight reduces right-to-left. reduce applies a binary operation without an initial value (requires non-empty collection). groupBy(f) partitions into a Map[K, List[V]]. sortBy, sortWith, zip, unzip, partition, span, take, drop, takeWhile, dropWhile — the full collection API replaces every loop pattern you have written in imperative languages.

scala
SCALA
// Immutable collection operations
val numbers = (1 to 20).toVector

// Chain transformations
val result = numbers .filter(_ % 2 == 0) // evens: [2,4,6,...,20] .map(n => n * n) // squares: [4,16,36,...,400] .takeWhile(_ < 200) // [4,16,36,64,100,144,196] .foldLeft(0)(_ + _) // sum: 460

println(result)  // 460

// For-comprehension: Pythagorean triples
val triples = for { c <- 1 to 100 b <- 1 to c a <- 1 to b if a*a + b*b == c*c
} yield (a, b, c)

triples.take(5).foreach(println)
// (3,4,5), (5,12,13), (6,8,10), (8,15,17), (9,12,15)

// groupBy: word frequencies
val words = 'the quick brown fox jumps over the lazy dog the'.split(' ')
val freq = words.groupBy(identity).view.mapValues(_.length).toMap
freq.toList.sortBy(-_._2).foreach { case (w, c) => println(s'$w: $c') }
Use .view before chaining many transformations on a large collection. A view makes the chain lazy — intermediate collections are not created. Call .toList, .toVector, or .force at the end to materialize the result.
📝 Day 2 Exercise Process Data with Collections
  1. Define a List of case class Student(name: String, grade: Int, score: Double)
  2. Find all students with score > 85 using filter
  3. Compute average score per grade using groupBy + mapValues(mean)
  4. Sort students by score descending and take the top 3
  5. Use a for-comprehension to find all pairs of students in the same grade

Supporting Resources

Go deeper with these references.

Scala Docs
Official Scala Documentation Complete Scala language specification, standard library reference, and tutorials.
Coursera
Functional Programming in Scala Martin Odersky's course on functional programming principles.
Apache
Apache Spark Documentation Official docs for Spark 3.x with Scala and Python API references.

Day 2 Checkpoint

Before moving on, make sure you can answer these without looking:

Continue To Day 3
Traits, Type Classes & Implicits