are not “planet-scale”? • Need at least 2 machines for fault tolerance! • Result: distributed system that is inherently concurrent Different from data-parallel system!
• Principles of composition and abstraction independent of program size • Cf. Guy Steele, “Growing a Language”, OOPSLA ‘98 Video: https://www.youtube.com/watch?v=_ahvzDzKdB0 Different notion of scalability!
(EPFL, Switzerland) • 1997: Pizza • Java extended with generic types, first-class functions, and ADTs/ pattern matching • 1998: GJ (“Generic Java”) • Odersky’s new javac adopted by Sun Microsystems • 1999–2001: Funnel • Since 2001: development of Scala • First public release: 2004-01-20 • First Scala conference 2008, first Scala Days conference 2010, Lausanne
not a solved problem ➟ development of new programming models • Futures, promises • async/await • STM • Agents • Actors • Join-calculus • Reactive streams • CSP • Async CML • … Which one is going to “win”?
asynchronous code def after[T](delay: Long, value: T): Future[T] Example Function for creating a Future that is completed with value after delay milliseconds
(_ <- 1 to 8) yield after1(1000, true) val later = after1(1000, true) How does it behave? Quiz: when is “later” completed? Answer: after either ~1 s or ~2 s (most often)
types and operations for managing data flow • There is very little support for control flow • For-comprehensions, ..? • Async complements Future and Promise with constructs to manage control flow
primitive is the “actor” [Hewitt et al. ’73] • Actors = concurrent “processes” communicating via asynchronous messages • Upon reception of a message, an actor may • change its behavior/state • send messages to actors (including itself) • create new actors • Fair scheduling • Decoupling: message sender cannot fail due to receiver Related to active objects
def receive = { case TaskFor(workers) => val from = sender val requests = (tasks zip workers).map { case (task, worker) => worker ? task } val allDone = Future.sequence(requests) allDone andThen { seq => from ! seq.mkString(",") } } } Using Akka (http://akka.io/)
nothing”: strong isolation of actors ➟ no race conditions • Actors handle at most one message at a time ➟ sequential reasoning • Asynchronous message handling ➟ less risk of deadlocks • No “inversion of control”: access to own state and messages in safe, direct way “Macro-step semantics”
of distributed systems • Message sends truly asynchronous • Message reception not guaranteed • Non-deterministic message ordering • Some implementations preserve message ordering between pairs of actors Therefore, actors well-suited as a foundation for distributed systems
notifications: a fundamental abstraction for web and mobile apps • Typically, event streams have to be scalable, robust, and composable • Enter reactive streams • Based on the duality of iterators and observers • Composition using higher-order functions • Key feature: asynchronous back-pressure www.reactive-streams.org Erik Meijer. “Your mouse is a database”: http://queue.acm.org/detail.cfm?id=2169076
protocols requires explicit tagging of messages ➟ not composable • Talk by Aleksandar Prokopec, “Reactors - Road to Composable Distributed Computing”, Scala Days Berlin 2016 See also: http://reactors.io/
shared state • Variable capture • “Spores”: Scala improvement proposal for safer closures (SIP-21) • Environment (captured variables) declared explicitly • Talk by Heather Miller at Scala Days 2014
Rust’s borrow checker • Haller and Odersky, “Capabilities for Uniqueness and Borrowing”, ECOOP ’10 • Ensure correct messaging protocols between actors • Session types? • Talk by Roland Kuhn, “Akka Typed: Between Session Types and the Actor Model”, Curry On! 2015
• Scala enables new ways to do concurrent, reactive, and distributed programming • Lots of exciting developments “[..] the purpose of abstracting is not to be vague, but to create a new semantic level in which one can be absolutely precise” Edsger W. Dijkstra. “The Humble Programmer”. ACM Turing Lecture 1972 https://www.cs.utexas.edu/~EWD/transcriptions/EWD03xx/EWD340.html