liveBook · Manning

Asynchronous programming

As explained in Functional Programming in Scala, Second Edition

An asynchronous computation is a computation whose execution can proceed independently of the caller without requiring the caller to wait synchronously for completion.

Asynchronous programming represents work that can proceed independently of its caller, allowing a program to describe computation without immediately waiting for completion. Purely functional designs treat asynchronous computations as values and defer execution to a separate interpreter. section 7.0 section 7.5

A functional asynchronous design emphasizes:

  • Avoiding shared mutable memory, which can produce race conditions, deadlocks, poor testability, and weak scalability. section 7.0
  • Combining computations with operations such as map, flatMap, and sequence before explicitly waiting for results. section 7.1.1 section 7.6
  • Separating a computation's description from the interpreter that runs it, so programs remain composable and reasoning stays focused on pure values. section 7.5 section 7.6

Delaying the wait

A parallel sum can construct two asynchronous computations, sumL and sumR, and combine them only after explicitly requesting their results. Calling get too early exposes waiting and can prevent the intended parallel execution; delaying get preserves the asynchronous structure until the boundary where the result is needed. section 7.1.1

Listing 13.5 Defining our Async type
enum Async[A]:
  case Return(a: A)
  case Suspend(resume: Par[A])
  case FlatMap[A, B](sub: Async[A],
                     k: A => Async[B]) extends Async[B]
 
  def flatMap[B](f: A => Async[B]): Async[B] =
    FlatMap(this, f)
 
  def map[B](f: A => B): Async[B] =
    flatMap(a => Return(f(a)))

Inspect the Async data type: Return represents a completed value, Suspend embeds a Par computation, and FlatMap sequences asynchronous steps. section 13.4

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Builds Par and Async representations, interpreters, combinators, and execution details rather than stopping at a definition.
Examples
Uses parallel sum, Par, Async constructors, interpreters, and parMap as concrete artifacts.
What it assumes
Assumes basic functional programming familiarity but develops the design through simple examples, experimentation, and progressively richer data types.
What you can do after
Build it from scratch by modeling asynchronous computations as values and implementing composable interpreters and combinators.
How it connects
Connects asynchronous programming with parallelism, pure functions, referential transparency, I/O, interpreters, and Free.

Also explained in

Compare how 28 books explain asynchronous programming →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in Scala, Second Edition. The section links point to the parts of the book it draws on.