A Summary of the for-Expression Lessons (Scala 3 Video)
As I mentioned at the beginning of these for
expression lessons, the book, Programming in Scala describes the translation rules for how the Scala compiler converts the for
comprehensions you write into a series of method calls that can include map
, flatMap
, foreach
, and withFilter
. As a reminder, those rules are:
- If a custom data type defines a
foreach
method, it allowsfor
loops (both with single and multiple generators). (Note the emphasis on the word “loops” in that definition. This refers to the simple Java-style use of afor
loop, i.e.,for (i <- ints) println(i)
.) - If a data type defines only
map
, it can be used infor
expressions consisting of a single generator. (Where “for
expressions” means for/yield expressions.) - If it defines
flatMap
as well asmap
, it allowsfor
expressions consisting of multiple generators. - If it defines
withFilter
, it allows for filter expressions starting with anif
within thefor
expression.
For a trait named CustomClass
, the signatures for these functions should look like this:
trait CustomClass[A] {
def map[B](f: A => B): CustomClass[B]
def flatMap[B](f: A => CustomClass[B]): CustomClass[B]
def withFilter(p: A => Boolean): CustomClass[A]
def foreach(b: A => Unit): Unit
}
Through a series of lessons I showed how you can write your own foreach
, map
, withFilter
, and flatMap
functions so that your custom data type can be used inside a for
expression.
As I noted several times in those lessons, I “cheated” a lot in these lessons because I’m not concerned at this point with how these methods are implemented. In future lessons I’ll show how to properly write these methods.
What’s next
As I mentioned in the first for
expression lesson, the goal of all of this work is to help you understand how FP code like this can possibly work:
def stackManip: State[Stack, Int] = for {
_ <- push(3)
a <- pop
b <- pop
} yield(b)
Now that you have the background on how to write a class that works in a for
expression, you’re much closer to being able to understand how this code works. The following lessons will build on what you just learned until the mysteries of this for
expression will be completely revealed.
See also
This is a list of articles that I either referenced in the for
expression lessons, or which otherwise helped with my understand of them.
- “Set comprehensions” defined on Wikipedia
- “Sequence comprehensions” on scala-lang.org
- How to use multiple generators in Scala ‘for’ expressions (loops)
- A collection of Scala ‘flatMap’ examples
- An example to show the differences between strict and lazy evaluation in Scala (filter vs withFilter)
- How does
yield
work? (includes a discussion ofwithFilter
versusfilter
) - A blog post titled, What’s in a Scala for comprehension also provides a discussion of why
withFilter
is preferred overfilter
in thefor
comprehension translation process - for expressions and ADTs
Update: All of my new videos are now on
LearnScala.dev