CTCaliberTek
Course: Scala 3 Developer Path: From First Program to a Tested Project · Lesson 2 of 8Log in to track your progress and earn a certificate when you finish the course.
Programming

Scala Values, Types, and Control Flow

Published November 9, 2026·Updated November 9, 2026·10 min read

Edited by , Senior Data Analyst. How we make our content

Like SaveLog in to like, save, and track progress.

Introduction

Scala is statically typed, which means the compiler knows the type of every value and catches many mistakes before the program runs, yet you rarely have to write the types because the compiler infers them. Another defining feature is that almost everything is an expression that produces a value, including if and match. This lesson covers the building blocks you will use in every program.

Prerequisites

  • Scala installed with Scala CLI (previous lesson)
  • A text editor

Step-by-Step Guide

Step 1: Prefer val over var

A val is an immutable binding: once assigned, it cannot point to something else. A var can be reassigned. Scala style strongly favors val, because code where values never change is easier to reason about and safer with multiple threads. Use var only when mutation is clearly simpler, for example a counter inside a small loop. The compiler infers the type from the right-hand side, but you can write it after a colon when you want to document it or choose a different type.

val name = "Asha"          // inferred String, cannot be reassigned
var visits = 0             // inferred Int, can be reassigned
visits = visits + 1

val price: Double = 19.99  // explicit type
// name = "Ben"            // compile error: reassignment to val

Step 2: Know the core types

The basic types are Int, Long, Double, Float, Boolean, Char, and String, all written with an initial capital letter, and they are objects with methods. Integer division truncates, so 7 divided by 2 is 3, and you must make one operand a Double to get a decimal. Numeric types do not convert implicitly in ways that lose information, so assigning a Double to an Int is a compile error, and you convert explicitly with methods such as toInt. The special type Unit, written as empty parentheses, means no useful value, like void in Java.

val count = 7
val half = count / 2          // 3 (integer division)
val exact = count / 2.0       // 3.5
val big = 3_000_000_000L      // Long literal
val letter = 'A'
val ok: Boolean = count > 5
println(exact.toInt)          // 3

Step 3: Format text with string interpolation

A string with the s prefix substitutes values written after a dollar sign, and curly braces let you embed a full expression. The f prefix adds printf-style formatting, such as two decimal places. Triple quotes create multi-line strings without escape sequences. These interpolators are checked at compile time, so a typo in a variable name is an error, not a runtime surprise as it can be with string concatenation.

val item = "notebook"
val qty = 3
val unit = 4.5
println(s"$qty x $item")                          // 3 x notebook
println(s"Total: ${qty * unit}")                  // Total: 13.5
println(f"Total with tax: ${qty * unit * 1.08}%.2f")   // 14.58
val text = """Line one
  |Line two""".stripMargin

Step 4: Use if as an expression

In Scala, if and else return a value, so there is no separate ternary operator. Assigning the result to a val keeps the logic compact and avoids declaring a mutable variable that you set in each branch. Both branches should produce the same type, otherwise the compiler infers a common supertype that is probably not what you meant. Scala 3 uses the then keyword, and indentation shows the structure.

val score = 82
val grade =
  if score >= 90 then "A"
  else if score >= 80 then "B"
  else if score >= 70 then "C"
  else "F"
println(s"Grade: $grade")   // Grade: B

Step 5: Branch with match

The match expression compares a value against a series of patterns and returns the result of the first one that fits. It is like a much more powerful switch statement. A pattern can be a literal, several alternatives separated by a vertical bar, a variable name that binds the value, or an underscore that matches anything. The compiler warns when a match on certain types does not cover every case, which prevents a class of bugs. You will use match heavily in the lesson on pattern matching.

val day = 6
val kind = day match
  case 6 | 7 => "weekend"
  case 1 | 2 | 3 | 4 | 5 => "weekday"
  case _ => "not a valid day"

val size = 120 match
  case n if n < 100 => "small"
  case n if n < 1000 => "medium"
  case _ => "large"

Step 6: Loop with for and while

A for loop iterates over any collection or range. The expression 1 to 5 includes five, while 1 until 5 stops before it. You can add guards with an if to filter items, and multiple generators to nest loops. A for loop with the yield keyword produces a new collection from the results, which you will use with collections later. The while loop works as in other languages but requires a var for the condition, which is a hint that functional alternatives often fit better.

for i <- 1 to 5 do println(i)

for i <- 1 to 10 if i % 2 == 0 do print(s"$i ")   // 2 4 6 8 10

val squares = for i <- 1 to 5 yield i * i         // Vector(1, 4, 9, 16, 25)

var n = 3
while n > 0 do
  println(n)
  n -= 1

FAQs

When should I use var instead of val?
Use val by default. Reach for var only for a tight local counter or accumulator where mutation is clearly simpler, and keep it inside a small function so the changing state cannot leak into the rest of the program.
Does Scala have null?
It exists for compatibility with Java, but idiomatic Scala avoids it and uses Option to represent a value that may be missing. A later lesson covers Option, Either, and Try for safe handling of missing values and errors.
Why is there no ternary operator?
Because if and else are already expressions that return a value, you can write val x = if cond then a else b directly. A separate operator would add nothing.

Summary

You learned the difference between val and var, the main value types and how they convert, how to build strings with interpolation, and how if, match, and for work as expressions that produce values. Thinking in expressions rather than statements is the key mindset shift in Scala. Next you will write functions and see how they can be passed around like any other value.

Related tutorials

Comments

Log in or create a free account to join the discussion.

  • No comments yet. Be the first to comment.