Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

MyList - step 6

Use Scala’s for-comprehension with MyList. Because we implemented map and flatMap, MyList already supports for-comprehension. We’ll also add withFilter to support if guards inside for.

For-comprehension basics

A for-comprehension like this:

val result = for
  a <- MyList(1, 2, 3)
  b <- MyList(a, a + 1)
yield b

Is desugared by the compiler roughly into:

MyList(1, 2, 3).flatMap(a => MyList(a, a + 1).map(b => b))

Since we already implemented map and flatMap, this just works.

Try it out

@main
def main(): Unit =
  val result = for
    a <- MyList(1, 2, 3)
    b <- MyList(a, a + 1)
  yield b

  println(result) // MyList(1, 2, 2, 3, 3, 4)

Filtering in for: withFilter

In for-comprehensions, if-guards (if a < 3) use withFilter under the hood (not filter). The standard library’s withFilter is lazy; we’ll keep it simple and make ours delegate to filter.

Add this to MyList:

trait MyList[A]:
  ...
  def withFilter(p: A => Boolean): MyList[A]

Implementation

override def withFilter(p: A => Boolean): MyList[A] = filter(p)

Example

@main
def main(): Unit =
  val result = for
    a <- MyList(1, 2, 3, 4, 5) if a < 3
  yield a

  println(result) // MyList(1, 2)

Key ideas

  • for-comprehension is syntax sugar that uses map, flatMap, and withFilter.
  • Providing withFilter allows if-guards in for without changing our existing filter behavior.