This is far from a serious proposal yet, and it’s entirely possible that what I’m suggesting here is infeasible – I’m not a compiler engineer, just a longtime hardcore Scala programmer. And this is more an initial concept, not deeply thought out. So consider this food for thought.
I’ve been watching the experiments towards adopting async/await with a fair amount of trepidation. Honestly, none of it feels like Scala to me - it feels like an ill-advised attempt to be trendy, with machinery that doesn’t have the generality of “good Scala”.
So I stepped back and asked, “What is the problem here? If I was king of the forest, how would I solve it?” And I find myself thinking that the problem isn’t that our concepts are all that hard – after all, async
tends to spread virally through the code the same way monads do, so folks should be used to that. The problem is that for
comprehensions just plain look weird and intimidating.
So in the spirit of the recent moves towards “quiet syntax”, I suggest “quiet for comprehensions”. To wit:
We elevate the <-
operator, making it legal inside of any val
. When detected, the compiler interprets that as the opening of what is effectively a for
comprehension, covering the rest of the block. The last expression of the block is interpreted as a yield
.
The result is that you can write code along these lines:
def userLogin(username: String, password: String): Future[UserInfo] = {
val dbReq = CheckUserLoginRequest(username, password)
val userId <- userDb.login(dbReq)
val profile <- profileDb.fetch(userId)
val avatar <- avatarDb.fetch(userId)
UserInfo(profile, avatar)
}
That’s approximately “direct syntax” in a nice clean way – quieter than current comprehensions but fully in line with how they work. I think it’s orthogonal to async/await, and less noisy. It’s limited in the same ways as for
, but good enough for the large majority of functions that I write, and I suspect would be a little more comfortable to people coming newly to Scala.
Anyway, something to consider. If it was doable, it would make a lot of modern Scala code less boilerplatey without changing anything other than a bit of surface syntax.