In Scala the for "loop" isn't actually a special language construct, but rather syntactic sugar. Your first example
val q2 = for {
c <- Coffees if c.price < 9.0
s <- Suppliers if s.id === c.supID
} yield (c.name, s.name)
translates to something in the lines of:
val q2 = Coffees.withFilter(_.price < 9.0).flatMap(c =>
Suppliers.withFilter(_.id === c.supID).map(s =>
(c.name, s.name)
)
)
Now, the flatMap, map, withFilter (and foreach) do not actually filter the collection, but rather collect what's hapening in an AST (Abstract Syntax Tree), which is then handled to Slick to translate to SQL.
Also, c.price, c.supID are actually Slick columns, whose <, >, === (and so on) methods don't return bool, but collect the comparison as well, which
is later passed down to be converted to SQL.
This is a talk by the creators, where most of this is described (correctly).