I'm curious why you'd call for-comprehensions powerful though. AFAIK they're just sugar over map/flatten/filter.
IME it's almost always more succinct and more readable to just call the methods you want directly.
Plus, you can say: map over an Option and transform both cases. You could also map then getOrElse, but readability suffers if your map is multi-line IMO. In the for-comprehension version you can't transform the None case.
I use for-comprehensions with Extractors in testing, because whatever. It's a test. So:
for {
Some(user) <- db.get[User](userId)
} yield otherStuff
Is fine in that case.Pattern Matching and Lifting are probably Scala's best features off the top of my head. Type Classes a close third.
But for-comprehensions are just sugar. They don't enable you to do anything you couldn't without them, and they actually make some flows impossible to write. I find that you can usually tame a nested mess with partial functions and a collect(). Or a fold() to handle your dual-transform.
That's just me though. Only been at the Scala job for a little over a year.
edit: @noelwelsh
I would nest yeah. But I'd see it more as a refactoring opportunity. Should authorization be in a for-comprehension? I'd instead add an AuthorizedAction in Play. That authenticated and provided a User from cache. So your example would look more like:
def show = AuthorizedAction.async { (user, permission) =>
actions.user(Read(permission, user))
}
I think I'd have to agree with another poster that doing all that inside of a for-comprehension would look like a code-smell to me.More than that, is map/flatten the right tool for the job for all this? Even if I wanted to do it inline, I'd probably prefer:
val perm = loginActions.mandatoryAuth(req)
val queryString = req.mandatoryParam[String](uuidParam).toClientProblem
(perm zip queryString) map {
case (Some(perm), CachedUser(user)) => actions.user(Read(perm, user))
case _ => BadRequest()
}
It's definitely subjective. I wouldn't fault anyone for using the for-comprehension (though I would encourage them to consider if it should rather be an Action), but describing it as "powerful" just doesn't sit right with me for some reason.Plus while you'll see for-comprehensions in the wild on occasion, I think it's a stretch to call them idiomatic. Unless you were going to constrain yourself to projects with ScalaZ as a dependency I suppose.