Day 1 of 5
⏱ ~60 minutes
Scala in 5 Days — Day 1

Scala Fundamentals & the JVM

Scala combines object-oriented and functional programming on the JVM. It is the language behind Apache Spark, Akka, and Kafka's Streams API. Today you learn Scala's type system, immutability, and how it interoperates with Java.

Scala on the JVM

Scala compiles to JVM bytecode — the same bytecode as Java. This means: access to every Java library, deployment on any JVM, and zero-cost Java interoperability. Scala can call Java methods directly; Java can call Scala classes. The Scala compiler adds type-safe abstractions that disappear at runtime (no overhead). Scala 3 (Dotty) modernized the language with cleaner syntax and improved type inference.

Values, Variables, and Types

val is immutable (like Java final); var is mutable. Prefer val — immutability prevents entire categories of bugs. Scala infers types: 'val x = 42' is an Int. Explicit annotation: 'val x: Int = 42'. Types: Int, Long, Double, Boolean, String, Char, Unit (void), Nothing (no value), Any (supertype of all), AnyRef (supertype of all reference types). String interpolation: s'Hello ${name}' (s-string) and f'${price}%.2f' (formatted).

Case Classes and Pattern Matching

Case classes are immutable value types with built-in equals, hashCode, toString, and copy. They enable exhaustive pattern matching. 'case class Point(x: Double, y: Double)' creates an immutable data class. Pattern matching: 'shape match { case Circle(r) => ... case Rectangle(w, h) => ... }'. The compiler warns if a match is not exhaustive. Sealed traits restrict which case classes can extend them — enabling total pattern matching.

scala
// Case classes: immutable value types
sealed trait Shape
case class Circle(radius: Double)          extends Shape
case class Rectangle(width: Double, height: Double) extends Shape
case class Triangle(a: Double, b: Double, c: Double) extends Shape

def area(shape: Shape): Double = shape match {
  case Circle(r)        => math.Pi * r * r
  case Rectangle(w, h)  => w * h
  case Triangle(a, b, c) =>
    val s = (a + b + c) / 2
    math.sqrt(s * (s-a) * (s-b) * (s-c))
}

// Collections: immutable by default
val shapes: List[Shape] = List(
  Circle(5.0),
  Rectangle(3.0, 4.0),
  Triangle(3.0, 4.0, 5.0)
)

val areas = shapes.map(area)
val total = areas.sum
println(s'Total area: ${total.formatted("%.2f")}')

// Option: null-safe optional value
def safeDivide(a: Double, b: Double): Option[Double] =
  if (b == 0) None else Some(a / b)

safeDivide(10, 2).foreach(r => println(s'Result: $r'))
safeDivide(10, 0).getOrElse(0.0)  // 0.0
💡
Prefer Option over null for values that might not exist. Option[A] is either Some(value) or None. It forces callers to handle the missing case. Null pointer exceptions are the most common runtime error in Java — Option eliminates them.
📝 Day 1 Exercise
Model a Domain with Case Classes
  1. Install Scala via coursier: curl -fL https://github.com/coursier/launchers/raw/master/cs-x86_64-pc-linux.gz | gzip -d > cs && ./cs setup
  2. Open the Scala REPL: scala
  3. Define case classes for a library: Book(title, author, isbn) and Library(books: List[Book])
  4. Write a findByAuthor(author: String): List[Book] method using filter
  5. Test exhaustive pattern matching: create a sealed trait Result with case classes Success and Failure

Day 1 Summary

  • Scala compiles to JVM bytecode with zero-cost Java interoperability
  • val is immutable (preferred); var is mutable
  • Case classes provide immutable data types with equals/hashCode/toString/copy
  • Sealed traits restrict subclasses, enabling exhaustive pattern matching
  • Option[A] replaces null — Some(value) or None, forced to handle both cases
Challenge

Model an e-commerce order system with Scala case classes: Product, OrderItem, Order, and OrderStatus (sealed trait with Pending/Shipped/Delivered/Cancelled). Write functions to calculate order total, apply discounts, and transition order status with pattern matching.

Finished this lesson?