4 ms·
async/await and removal of the case-class/tuple 22 field limit are the big ones I think. (edit: the limit is still in effect for Tuple apparently. Only removed
by ssmoot 13y ago
async/await and removal of the case-class/tuple 22 field limit are the big ones I think. (edit: the limit is still in effect for Tuple apparently. Only removed for case-classes.)
In database (or Actor ask) heavy code dealing with a lot of Futures async/await has the potential to fairly significantly influence code style. for-comprehensions often don't cut it when you're dealing with a Future[Option[User]] and need to pull in their assigned roles from a Future[Seq[Role]].
val userOption = db.get(userId) flatMap {
case None => Future.successful(None)
case Some(user) =>
Future.sequence {
user.roleIds map(db.get(_))
} map { roles =>
Some(user.copy(roles = roles.flatten))
}
}
vs:
val userOption = async {
for {
user <- await(db.get(userId))
roles = await(Future.sequence(user.roleIds map(db.get(_))))
} yield user.copy(roles = roles.flatten)
}
Or something like that anyways.
- neverminder 13y agoTuple field limit was not removed, there are comments below regarding that.
- runT1ME 13y ago> for-comprehensions often don't cut it when you're dealing with a Future[Option[User]] and need to pull in their assigned roles from a Future[Seq[Role]]. If you aren't familiar with Monad Transformers, yes, it can be tricky. However it's trivial using an Option monad transformer (OptionT[Future,A]]) to have the same semantics. for { user <- OptionT(db.get(userId) mappedRoles = user.roleIds.map(db.get(_)) roles <- mappedRoles.sequence.liftM //goes to OptionT[Future,A]] } yield user.copy(roles = roles.flatten) Look at http://github.com/scalaz http://github.com/scalaz for already built Monad Transformers (Either/State/Option/Writer) that will work with the standard lib Future along with tons of other goodies. I actually actively dislike the async stuff as it gives you another way of doing the same thing, at a less powerful abstraction.
- ssmoot 13y agoI've used ScalaZ a bit (don't remember exactly why, but something to do with Future transformations), but I found it to crush the compiler. Especially combined with IntelliJ. I like the async/await stuff. Especially after attending the ScalaDays presentation on it. The idea that it produces a state machine in the background feels like it's very easy to reason about. I actually (personally) find for-comprehensions the least useful feature of Scala probably. They rarely produce the most readable code IME with just a couple transformations in play, and it's not often I find myself dealing with compatible types in the more complex cases. So I guess I consider async/await the readable/prettier alternative to direct mapping that for-comprehensions mostly fail to deliver on. for-comprehensions are probably Scala's second biggest wart IMO (not harmful, more just mostly useless). YMMV. Sort of like `__DATA__` or `=BEGIN/=END` in Ruby.
- runT1ME 13y agoFor comprehension is probably Scala's most powerful feature aside from higher kinded types. You may not see the advantage of for comprehension for sequencing a few operations over Future. However, when you have a large number of calls you have to sequence along with filter (which for comprehension can do) it's indispensable. Check this out: https://www.youtube.com/watch?v=MHw-dDxC8Z4 https://www.youtube.com/watch?v=MHw-dDxC8Z4
- Paradigma11 13y agoI disagree. I can only talk about f# but for me the comprehension syntax is mostly an aesthetic choice: [1..100] |> List.filter (fun e -> e % 2=0) |> List.map (fun e -> e * 2) or: [for e in 1 .. 100 do if e % 2=0 then yield e * 2] Personally i prefer the first one since it's compositional and more like a dataflow. But i am not familiar with Scala so maybe i am missing something.
- kasey_junk 13y agoI've actually gotten to the point where I think for comprehensions are a code smell. The only time I prefer the for syntax is when I have a large list of monad chains. Large lists of monad chains almost always indicate some sort of poor factoring of the code.