5 ms·
I started using Scala ~2.5 years ago for my undergrad thesis. At the time I didn't really know what I was doing and essentially wrote Java with map/reduce on c
by saryant 13y ago
I started using Scala ~2.5 years ago for my undergrad thesis. At the time I didn't really know what I was doing and essentially wrote Java with map/reduce on collections.
I've been working steadily in Scala since and currently do so professionally. I'm a fan, especially with the Akka actor framework.
Lately I've been playing with Play, Akka and ReactiveMongo. For-comprehensions offer a terrific abstraction for dealing with asynchronous code. My current side project is "Street View for Flights" implemented in the above stack. Lots of calls to third-party REST APIs after checking if data has already been retrieved and inserted into Mongo. Code like the following allows for controllers to be asynchronous while staying readable:
def byCode(airlineCode: String) = Action {
Async {
for {
airline <- Airline.findByICAO(airlineCode) // returns Future[Option[Airline]]
} yield airline map { a =>
views.html.airline(a)
} getOrElse NotFound
}
}
The advantage for me is that those futures could be redeemed either by finding the requested object in Mongo and on failure retrieving it from a third-party API while not blocking and keeping the code readable. Either way, the controller just gets a Future without blocking.
Other parts of this project make heavy use of Akka actors to feed server-sent events (sort of a compromise between Comet and WebSockets). Development has been great fun because Scala really allows me to write code at a higher level. Asynchronous, typesafe, nullsafe code with the compiler as my safety net.
- yareally 13y agoActors and the way Scala handles async is one of the reasons I wanted to get into using Scala on Android actually. The awkward way Android handles it is chock full of Java boilerplate and Scala's way is just much more elegant. Another feature that got my attention was the ability to have a SQL framework that handled things similar to LINQ. I haven't tried it much yet, but Squeryl[1] has looked promising for being a Scala equivalent. I may have to look into Akka more though as that will easily take care of async SQLite calls as well[2]. [1] http://squeryl.org/introduction.html http://squeryl.org/introduction.html [2] http://www.gamlor.info/wordpress/2012/05/async-sql-and-akka/ http://www.gamlor.info/wordpress/2012/05/async-sql-and-akka/
- saryant 13y agoI used Squeryl in my thesis (admittedly a while ago) and Slick[1] on a more recent project. Like you, I had ample experience in LINQ and it's definitely the feature I missed most from C#. I'm a fan of Slick. I'm also looking forward to async SQL calls. I've been building some Akka-based projects for a client and both they and I have been thrilled with the results. They're a startup that's gaining traction and they brought me in to help with scalability. I won't go so far as to say that Akka is a magic bullet but it makes reasoning about scalability far easier, though in our case we're mostly dancing around the IO bottleneck. [1] http://slick.typesafe.com/ http://slick.typesafe.com/
- clhodapp 13y agoMy GSOC project for this year is an extension to for comprehensions to enable LINQ-like conciseness without LINQ's inflexibility. If it ends up being merged into the compiler proper (a pretty big if), it should really help to make writing complex queries a lot less painful.
- gtani 13y agoThat's excellent. 9 of 14 proposed projects were accepted http://www.scala-lang.org/gsoc2013 http://www.scala-lang.org/gsoc2013 http://www.google-melange.com/gsoc/projects/list/google/gsoc2013?ModPagespeed=noscript http://www.google-melange.com/gsoc/projects/list/google/gsoc... (type "scala team" in "Organization" box
- mynameisme 13y agoSqueryl doesn't allow you to drop down to raw SQL, so I'd suggest avoiding it.
- papsosouid 13y agoIt is also rather broken, and the author doesn't appear to care. I'd second the suggestion to avoid it.
- laureny 13y agoThe main problem I have with actors is that they are untyped. What's the point of having a powerful type system like Scala's and then throw it out of the window just so I can use a distributed framework?
- saryant 13y agoMy understanding is that the new typed channels feature in the upcoming Akka 2.2 release will address this. The macro feature introduced in Scala 2.10 makes this possible. http://doc.akka.io/docs/akka/2.2.0-RC1/scala/typed-channels.html http://doc.akka.io/docs/akka/2.2.0-RC1/scala/typed-channels....
- yareally 13y agoIt's possible to make them typed with the stdlib[1]. Link also gives some reasons as to why they're untyped. Short answer is it started as a way to replicate Erlang in Scala[2]. [1] http://stackoverflow.com/questions/5547947/why-are-messages-to-akka-actors-untyped http://stackoverflow.com/questions/5547947/why-are-messages-... [2] http://article.gmane.org/gmane.comp.lang.scala/12988 http://article.gmane.org/gmane.comp.lang.scala/12988
- noelwelsh 13y agoScalaz has some nice (usefully typed) concurrency tools: https://github.com/scalaz/scalaz/tree/scalaz-seven/concurrent/src/main/scala/scalaz/concurrent https://github.com/scalaz/scalaz/tree/scalaz-seven/concurren... https://github.com/scalaz/scalaz-stream https://github.com/scalaz/scalaz-stream Like everything with Scalaz, the tools are great but almost completely undocumented.
- laureny 13y ago> Like everything with Scalaz, the tools are great but almost completely undocumented. Exactly. I will start considering scalaz once its authors grow up and realize that the lack of documentation is not a sign of quality.
- 13y ago
- Uchikoma 13y agoFrom my point of view and understanding, for is not good for this. Isn't it blocking? Say you have for a <- forA b <- forB c <- forC(a) it does not do a and b in parallel and then c, or does it?
- noelwelsh 13y agoIt depends. Let's imagine forA, and forB are expressions that evaluate to futures of Ints. This runs them in serial: for { a <- forA b <- forB } yield a + b This runs them in parallel: val fa: Future[Int] = forA val fb: Future[Int] = forB for { a <- fa b <- fb } yield a + b (I dropped forC from your example as it has a dependency on the result for forA, and thus can't run in parallel.)
- Uchikoma 13y agoThat forC has a dependency on a was the intention, so it needs to be run in serial. I can't see the difference between your examples and so am confused why 1.) is serial 2.) is parallel.
- noelwelsh 13y agoAt the risk of being trite, it's down to the order of evaluation. You know that a for comprehension expands into calls to flatMap and map? So for { a <- forA b <- forB } yield a + b expands to forA flatMap { a => forB map { b => a + b } } Remember that forB creates and returns a future. Only when this future has been created will it start running. It should be apparent that forB is not evaluated till forA's future delivers a value, and thus the future returned by forB will run in serial with the future returned by forA. In the other example the futures are created outside of the for comprehension, and thus start running in parallel.
- Uchikoma 13y agoAh ok, thanks!
- deleted 13y ago
- the1 13y agolet's say you have more than one future: findAirline: AirlineCode => Future[Option[Airline]] getFlightsForToday: Airline => Future[Seq[Flight]] findAvailable: Seq[Flight] => Constraints => Future[Option[Flight] compose them so that I get: findFlight: AirlineCode => Constraints => Future[Flight] I don't want `Future[Option[Flight]]` since Future has own error handling (using Try). No cheating by using scalaz monad transformer.
- yummyfajitas 13y agodef getOrThrow[T](x: Option[T]): T = x.getOrElse(throw new AirlineError) def findFlight(code: AirlineCode, constraints: Constraints) = for { airline <- findAirline(code).map(getOrThrow) flights <- getFlightsForToday(airline) available <- findAvailable(flights, constraints).map(getOrThrow) } yield (available) No idea why you consider using scalaz to be cheating.
- the1 13y agoah, getOrThrow! nice.
- saryant 13y agoI'll readily admit that my Scala isn't 100% idiomatic, I'm still learning!