0Pricing
Scala for Backend Engineering & Functional Programming · Lesson

Filtering with if

Guards in comprehensions.

Filtering with if is a free Scala for Backend Engineering & Functional Programming lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Scala for Backend Engineering & Functional Programming learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Guards in for-comprehensions

Inside a for-comprehension you can add an if condition called a guard. It keeps only the elements that satisfy the condition, just like filter.

object Main {
  def main(args: Array[String]): Unit = {
    val evens = for (x <- 1 to 10 if x % 2 == 0) yield x
    println(evens)
  }
}

Guards desugar to withFilter

A guard if cond is rewritten into a call to withFilter (a lazy variant of filter).

  • for (x <- xs if p(x)) yield x
  • becomes xs.withFilter(p).map(x => x)
object Main {
  def main(args: Array[String]): Unit = {
    val sugar = for (x <- List(1, 2, 3, 4) if x > 2) yield x
    val desugared = List(1, 2, 3, 4).withFilter(_ > 2).map(x => x)
    println(sugar == desugared)
  }
}

Why withFilter, not filter

withFilter is lazy: it does not build an intermediate collection. The condition is applied only when the following map or flatMap runs, which saves memory and work.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4, 5, 6)
    val result = for (n <- nums if n % 3 == 0) yield n * 100
    println(result)
  }
}

Multiple guards

You can chain several guards. They combine like a logical AND: an element must satisfy all conditions to survive.

object Main {
  def main(args: Array[String]): Unit = {
    val result = for {
      x <- 1 to 20
      if x % 2 == 0
      if x % 3 == 0
    } yield x
    println(result)
  }
}

Guards with multiple generators

Guards can appear after any generator and filter that level of iteration. Place the guard right after the generator whose values it tests.

object Main {
  def main(args: Array[String]): Unit = {
    val coprimeSums = for {
      x <- 1 to 3
      y <- 1 to 3
      if x != y
    } yield (x, y)
    println(coprimeSums)
  }
}

Combining a guard and a value binding

You can freely mix guards (if) with value bindings (=). Order matters: a binding defined before a guard can be used inside that guard.

object Main {
  def main(args: Array[String]): Unit = {
    val result = for {
      x <- 1 to 6
      square = x * x
      if square > 10
    } yield square
    println(result)
  }
}

Guards on String collections

Guards work with any predicate, not just numeric ones. Here we filter words by length.

object Main {
  def main(args: Array[String]): Unit = {
    val words = List("scala", "go", "java", "rust", "c")
    val longWords = for (w <- words if w.length >= 4) yield w.toUpperCase
    println(longWords)
  }
}

Filtering Options

For an Option, a guard that fails turns the result into None. This makes for-comprehensions a clean way to validate optional values.

object Main {
  def main(args: Array[String]): Unit = {
    val ok  = for (x <- Some(8) if x > 5) yield x
    val bad = for (x <- Some(3) if x > 5) yield x
    println(ok)
    println(bad)
  }
}

Guard position changes meaning

A guard only sees values bound above it. Putting it before a generator that it needs will not compile. Always place a guard after the relevant generator.

object Main {
  def main(args: Array[String]): Unit = {
    val result = for {
      x <- 1 to 3
      y <- 1 to 3
      if x + y == 4
    } yield s"$x + $y = ${x + y}"
    result.foreach(println)
  }
}

Guards versus a final filter

You could filter the result after the comprehension, but a guard filters during iteration. With multiple generators, guards can prune branches early, doing less total work.

object Main {
  def main(args: Array[String]): Unit = {
    val withGuard = for {
      x <- 1 to 100
      if x % 25 == 0
    } yield x
    println(withGuard)
  }
}

Readable validation pipelines

Stacking guards reads like a checklist of conditions. This is one of the most idiomatic uses of for-comprehensions in real Scala code.

object Main {
  def main(args: Array[String]): Unit = {
    val valid = for {
      n <- List(4, 7, 12, 15, 20)
      if n > 5
      if n < 18
      if n % 2 == 0
    } yield n
    println(valid)
  }
}

Quick Check

What method does a guard (if) in a for-comprehension desugar into?

Recap

You learned about guards in for-comprehensions:

  • if cond filters elements during iteration
  • Guards desugar to withFilter (lazy filtering)
  • Multiple guards combine like logical AND
  • A guard only sees values bound above it
  • Guards mix freely with generators and = bindings

Frequently asked questions

Is the “Filtering with if” lesson free?

Yes — the full text of “Filtering with if” is free to read here on the web, and the Scala for Backend Engineering & Functional Programming course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Scala for Backend Engineering & Functional Programming course, upgrade to CoddyKit PRO.

What will I learn in “Filtering with if”?

Guards in comprehensions. You practise Scala for Backend Engineering & Functional Programming with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Scala for Backend Engineering & Functional Programming?

No prior experience is required. Scala for Backend Engineering & Functional Programming on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Filtering with if” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Scala for Backend Engineering & Functional Programming lesson?

Yes. Every Scala for Backend Engineering & Functional Programming lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Desugaring for
  2. Filtering with if
  3. Multiple Generators
  4. Using with Option and Future
← Back to Scala for Backend Engineering & Functional Programming