As far as I understand it, For Comprehensions are a way to write a chain of flatMap calls. So far so good, that I understand to a certain extend.
That leads me to my question: Why is it called For Comprehension, why much the decision on “for”? Where is the connection between flatMap and for, where for is as well used for iterating and looping?
Maybe, if I understand this I can better understand the anatomy of For Comprehensions.
AFAIK just because for collections map and flatMap represent (nested) iterations, so it is like a for each loop.
So if you have something like:
val userCountries = for {
user <- users
address <- user.addresses
} yield address.country
You can read it like: “For each user in users and each address on the user addresses, then collect all the addresses countries into the variable userCountries”.
Now, when you look at other effects like Option, Either, Future, IO, etc, while the idea of “iteration” is weirder, the wording still makes sense.
def process: Either[Error, String] = ???
val result = for {
rawData <- process
cleanData <- rawData.toIntOption.toRight(left = "Bad number")
} yield cleanData
You can read it like: “For some raw data coming from the process, and for a cleaned data extracted from the raw data, collect the cleaned data on the result variable”.
So the wording is weird but still somewhat clear.
Yeah, exactly. In no small part, it makes it way easier for folks who are coming in from other languages.
I generally start out by teaching them that it’s more or less what they understand as a typical for-loop (in particular, many languages now have a concept of “loop over each element in this collection”), and then later ease them into The Joy of Monads.
Also remember, that Scala allows impure code and there are also people using it in a more imperative way. If you use for without yield, it isn’t translated to flatMap and map calls, but to foreach calls. For people coming from imperative languages, this means they can use for like a for-each-loop in other languages, and then just add a yield to get a “for loop which returns a new collection”.