Scala 2.11.0 Release Notes
scala-lang.org
scala-lang.org
It's also by Martin Odersky, but also with Erik Meijer and Roland Kuhn.
Reactive is split into three "subclasses". The beginning part, taught again by Odersky, was a pretty useful extension of what was taught in the first class. As with the first class, the lectures were very well thought out. Although, some of the examples abandon the beauty of side-effect free programming, which was a letdown after really being turned on to that style in the first course.
The middle section on Futures and ScalaRx was pretty rough. Those lectures, done by Erik Meijer (I believe), were less clear and less well planned. I don't know if there's an impedance mismatch between Scala and the reactive style or if ScalaRx is just the wrong abstraction, but the joy of Scala was completely lost for me in these two lectures. I'm used to Javascript's Promises/Deferreds, which are essentially the same thing as Scala's Futures/Promises, but the former are far more intuitive syntactically.
I did, however, find the final three lectures on Akka to be very well taught. I had no experience on actor model programming, but I came away very intrigued by the possibilities.
A complaint that spans all three sections was that the assignments could be better focused on the the concepts at hand. Each can require a fair bit of constructing your own test and debugging frameworks to figure out how to pass the rather opaque and unhelpful automatic grading system. I eventually lost patience and quit doing the assignments after floundering with the tools.
Erik Meijer's lectures -- at least in the first iteration of the course; maybe they've gotten better -- were riddled with errors, confusing exercises, and an overall lack of coherence with the rest of the course. It pains me to say this because Erik seems like a cheerful guy and I really wanted to like his lectures, but they are a mess.
Even Roland Kuhn's lectures, which are pretty good and a lot clearer than Erik's, didn't manage to sell reactive programming to me. One glaring problem was that the actor model seems to throw away most of Scala's static type checking, which we had learned on the previous functional course. Suddenly it's ok to pass whatever message to actors in a way that seems closer to dynamic typing.
See http://noelwelsh.com/programming/2013/03/04/why-i-dont-like-... and http://www.chrisstucchio.com/blog/2013/actors_vs_futures.htm...
Having that said, if all you want is to "switch from imperative language X to Scala", (e.g. from Java) and you want to learn first how to do the "non functional" stuff in Scala, then keep in mind that this course is teaching functional programming first, Scala later. You can do (if you want) very imperative and object oriented style of coding in Scala but this course is not focusing on that part of the language (not because it's bad, but simply because the course is about functional programming)
With that said, go and enroll, it's one of the best coursera courses I took. Great videos, and very interesting programming assignments (many are adaptations from SICP I later learned) and great forum discussions.
Very nice, with a focus on interpretation and comparison points between paradigms.
Curious to test out build times in 2.11, sounds like some minor gains have been made there, and more to come in the 2.11 release cycle as the new scalac optimiser is integrated (http://magarciaepfl.github.io/scala/)
SBT does the heavy lifting (have automatic build turned off in Eclipse) while Eclipse provides the dev environment.
Really snappy, zero spurious errors, it's like night and day compared to 3 years ago, woo hoo ;-)
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.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 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.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.
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
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.
Large lists of monad chains almost always indicate some sort of poor factoring of the code.
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.
for {
perm <- loginActions.mandatoryAuth(req)
queryString <- req.mandatoryParam[String](uuidParam).toClientProblem.fv
user <- stringToUser(cache.user, queryString).fv
result <- actions.user(Read(perm, user))
} yield result
Then you get into nested monads (e.g. Either can represent a computation that succeeds or fails, which you want to contain inside a Future) and you use monad transformers to squish them into one single monad, to avoid nesting for comprehensions.1. Not using Play, so that's moot.
2. The monad type is not an Option, it's more like Future[Either[Problem, Response]], Caches, for instance, return Futures.
3. That was the simplest for comp I could find. Most of them are much longer. You'd have to be batshit crazy to write nested flatMaps for them.
Java 8 is the most exciting release since Java 2 in my opinion.
There's quite lot of discussion around the compiler performance improvements.
I've bumped up against that limit pretty bad while trying to deserialize json. Shapeless did a lot to solve the problem, but I'm sure glad that limit has been removed.
Increasing the limit would create too much bytecode, and in the current design, lifting the limit is just impossible (without runtime code generation or custom classloader, etc.).
You could also work at evangelizing Scala in your current (presumably) Java shop. I've found success with this approach by getting other developers interested in the language and mentoring them, especially during the steeper parts of the learning curve. If you can pique the interest of a good portion of the development team it's often not too difficult to get a new language introduced through smaller non-critical or non-production systems, which is a good foothold with which to get the benefits visible to the wider group. YMMV of course.
Even this low bar eliminates 90% of candidates so it won't take much for you to shine at this level.
If you're snr then you might find yourself actually having to introduce Scala at a Java shop. Run dojos, lunchtime lightning/brown bag talks and lever it in as a testing framework or throwaway prototype. If that doesn't work, start questioning what you did to deserve being called snr.
jared at nestlabs dot com
https://speakerdeck.com/heathermiller/spores-distributable-f...
2.11 set the tone for the remainder of the 2.x cycle: smaller, faster, stabler. 2.12 will focus on Java 8 support and making it (even) easier to learn and use Scala.
We're also working on making the compiler a better platform for others to innovate on -- originally via compiler plugins, now using reflection & macros. A lot of cool stuff is happening outside core Scala, such as scala.js, and we hope to spur on that trend.
(I'm the Scala Tech Lead at Typesafe.)
Part of the solution will be tooling, and the team at EPFL has started prototyping a migration tool that generates patches to turn a well-typed Scala 2 program into the equivalent one on Scala 3. I believe our type system and the fact that we're a compiled language will make a big difference compared to Python.
Naturally, tradeoffs will be made, are you guys at a point yet where you can reveal what we're going to _lose_ in terms of functionality and flexability?
I know the core Scalaz developers had a bit of an uproar on Twitter when Dotty was first revealed (due to the simplified/less powerful type system in Dotty that may make some scalaz magic very difficult to pull off).
Otherwise, improved tooling, build times, Scala 2 sans les warts, etc. will be a boon for the language.
So, Scala 3.0-M1 in 2016? Give us the inside word ;-)