I am familiar with the concept that Scala's for comprehensions are just syntactic sugar for monadic operations (map, withFilter, foreach, and flatMap) and the desugaring is described in this popular answer.
By that logic, I was surprised to find that, when using pattern matching as part of the assignment portion of a for comprehension, no MatchError is thrown when the pattern doesn't match an element. Instead, the non-matched element is filtered out:
case class Account(id: String, role: String)
val accounts = Set(Account("a", "ADMIN"), Account("b", "USER"), Account("c", "ADMIN"), Account("d", "USER"), Account("e", "USER"))
val adminIds = for (Account(id, "ADMIN") <- accounts) yield id
// Set("a", "c") (no MatchError on Account("b", "USER")!
I would have expected that comprehension to translate to something like this:
val adminIds = accounts.map { case Account(id, "ADMIN") => id }
// or maybe
val adminIds = accounts.map { account =>
val Account(id, "ADMIN") = account
id
}
But of course those would throw a MatchError. Instead it seems more similar to this:
val adminIds = accounts.collect { case Account(id, "ADMIN") => id }
However, I've never seen any mention of a for comprehension desugaring into a collect call.
So how is this done under the hood?