SlideShare a Scribd company logo
Direct Style Scala
Martin Odersky
EPFL
Scalar Conference
March 24, 2023
Shifting Foundations
Trends
Widespread support for async/await
Runtimes get better support for fibers or continuations.
Examples
Goroutines,
Project Loom in Java,
Kotlin coroutines,
OCaml or Haskell delimited continuations,
Research languages such as Effekt, Koka
Thesis of this talk
This will deeply influence libraries and frameworks
It’s very attractive now to go back to direct style.
Shifting Foundations
Trends
Widespread support for async/await
Runtimes get better support for fibers or continuations.
Examples
Goroutines,
Project Loom in Java,
Kotlin coroutines,
OCaml or Haskell delimited continuations,
Research languages such as Effekt, Koka
Thesis of this talk
This will deeply influence libraries and frameworks
It’s very attractive now to go back to direct style.
How will this influence Scala in the future?
1 There will likely be native foundations for direct-style reactive
programming
Delimited continuations on Scala Native
Fibers on latest Java
Source or bytecode rewriting for older Java, JS
2 This will enable new techniques for designing and composing
software
3 There will be a move away from monads as the primary way
of code composition.
Building a Direct-Style Stack
First step: Boundary/break
Error handling
Suspensions
Concurrency library design built on that
Building a Direct-Style Stack
First step: Boundary/break
(shipped)
Error handling
(enabled)
Suspensions
(wip)
Concurrency library design built on that
(wip)
Warmup: Boundary/break
A cleaner alternative to non-local returns (which will go away)
def firstIndex[T](xs: List[T], elem: T): Int =
boundary:
for (x, i) <- xs.zipWithIndex do
if x == elem then break(i)
-1
boundary establishes a boundary
break returns with a value from it.
Stack View
API
package scala.util
object boundary:
final class Label[-T]
def break[T](value: T)(using label: Label[T]): Nothing =
throw Break(label, value)
inline def apply[T](inline body: Label[T] ?=> T): T = ...
end boundary
To break, you need a label that represents the boundary.
In a sense, label is a capability that enables to break.
(This is a common pattern)
Implementation
The implementation of break produces efficient code.
If break appears in the same stackframe as its boundary, use a
jump.
Otherwise use a fast exception that does not capture a stack
trace.
A stack trace is not needed since we know the exception will be
handled (*)
(*) To be 100% sure, this needs capture checking.
Implementation
The implementation of break produces efficient code.
If break appears in the same stackframe as its boundary, use a
jump.
Otherwise use a fast exception that does not capture a stack
trace.
A stack trace is not needed since we know the exception will be
handled (*)
(*) To be 100% sure, this needs capture checking.
Stage 2: Error handling
boundary/break can be used as the basis for flexible error handling.
For instance:
def firstColumn[T](xss: List[List[T]]): Option[List[T]] =
optional:
xss.map(_.headOption.?)
Optionally, returns the first column of the matrix xss.
Returns None if there is an empty row.
Error handling implementation
optional and ? on options can be implemented quite easily on top
of boundary/break:
object optional:
inline def apply[T](inline body: Label[None.type] ?=> T)
: Option[T] = boundary(Some(body))
extension [T](r: Option[T])
inline def ? (using label: Label[None.type]): T = r match
case Some(x) => x
case None => break(None)
Analogous implementations are possible for other result types such
as Either or a Rust-like Result.
My ideal way of error handling would be based on Result + ?.
Stage 3: Suspensions
Question: What if we could store the stack segment between a
break and its boundary and re-use it at some later time?
Suspensions
Question: What if we could store the stack segment between a
break and its boundary and re-use it at some later time?
This is the idea of delimited continuations.
Suspensions
Question: What if we could store the stack segment between a
break and its boundary and re-use it at some later time?
This is the idea of delimited continuations.
Suspension API
class Suspension[-T, +R]:
def resume(arg: T): R = ???
def suspend[T, R](body: Suspension[T, R] => R)(using Label[R]): T
Suspensions are quite powerful.
They can express at the same time algebraic effects and monads.
Generators
Python-style generators are a simple example of algebraic effects.
def example = Generator:
produce(”We’ll give you all the numbers divisible by 3 or 2”)
for i <- 1 to 1000 do
if i % 3 == 0 then
produce(s”$i is divisible by 3”)
else if i % 2 == 0 then
produce(s”$i is even”)
Here, Generator is essentially a simplified Iterator
trait Generator[T]:
def nextOption: Option[T]
Algebraic Effects
Task: Build a generate implementation of Generator, so that one
can compute the leafs of a Tree like this:
enum Tree[T]:
case Leaf(x: T)
case Inner(xs: List[Tree[T]])
def leafs[T](t: Tree[T]): Generator[T] =
generate: // effect scope
def recur(t: Tree[T]): Unit = t match
case Tree.Leaf(x) => produce(x) // effect
case Tree.Inner(xs) => xs.foreach(recur)
recur(t)
Generator Implementation
trait Produce[-T]:
def produce(x: T): Unit
def generate[T](body: Produce[T] ?=> Unit) = new Generator[T]:
def nextOption: Option[T] = step()
var step: () => Option[T] =
The Step Function
trait Produce[-T]: // effect type
def produce(x: T): Unit
def generate[T](body: Produce[T] ?=> Unit) = new Generator[T]:
def nextOption: Option[T] = step()
var step: () => Option[T] = () =>
boundary:
given Produce[T] with // handler
def produce(x: T): Unit =
suspend[Unit, Option[T]]: k =>
step = () => k.resume(())
Some(x)
body
None
Summary: Algebraic Effects
Effects are methods of effect traits
Handlers are implementations of effect traits
They are passed as implicit parameters.
They can abort part of a computation via break
They can also suspend part of a computation as a
continuation and resume it later.
Implementing Suspensions
There are several possibilities:
Directly in the runtime, as shown in the designs
On top of fibers (requires some compromises)
By bytecode rewriting (e.g. Quasar, javactrl)
By source rewriting
Suspensions and Monads:
Wadler (1993): Continuations can be expressed as a monad.
“Haskell is the essence of ML”
Filinski (1994): Every monad can be expressed in direct style
using just delimited continuations.
“ML is the essence of Haskell”
My take: designs based on continuations are simpler to compose
than monads.
Suspensions and Monads:
Wadler (1993): Continuations can be expressed as a monad.
“Haskell is the essence of ML”
Filinski (1994): Every monad can be expressed in direct style
using just delimited continuations.
“ML is the essence of Haskell”
My take: designs based on continuations are simpler to compose
than monads.
Direct-Style Futures
With suspend(*), we can implement lightweight and universal
await construct that can be called anywhere.
This can express simple, direct-style futures.
val sum = Future:
val f1 = Future(c1.read)
val f2 = Future(c2.read)
f1.value + f2.value
Structured concurrency: Local futures f1 and f2 complete before
sum completes. This might mean that one of them is cancelled if
the other returns with a failure.
(*) Loom-like fibers would work as well.
Compare with Status Quo
val sum =
val f1 = Future(c1.read)
val f2 = Future(c2.read)
for
x <- f1
y <- f2
yield x + y
Composition of futures is monadic
but creation isn’t, which is a bit awkward.
A Strawman
lampepfl/async is an early stage prototype of a modern, low-level
concurrency library in direct style.
Main elements
Futures: the primary active elements
Channels: the primary passive elements
Async Sources Futures and Channels both implement a new
fundamental abstraction: an asynchronous source.
Async Contexts An async context is a capability that allows
a computation to suspend while waiting for the result of an
async source.
Link: github.com/lampepfl/async
Futures
The Future trait is defined as follows:
trait Future[+T] extends Async.Source[Try[T]], Cancellable:
def result(using Async): Try[T]
def value(using Async): T = result.get
The result method can be defined like this:
def result(using async: Async): T = async.await(this)
async is a capability that allows to suspend in an await method.
Futures
The Future trait is defined as follows:
trait Future[+T] extends Async.Source[Try[T]], Cancellable:
def result(using Async): Try[T]
def value(using Async): T = result.get
The result method can be defined like this:
def result(using async: Async): T = async.await(this)
async is a capability that allows to suspend in an await method.
Async
The Async trait is defined as follows:
trait Async:
def await[T](src: Async.Source[T]): T
def scheduler: ExecutionContext
def group: CancellationGroup
def withGroup(group: CancellationGroup): Async
await gets the (first) element of an Async.Source.
It suspends if necessary.
Async.Source
Futures are a particular kind of an async source. (Other
implementations come from channels).
Async sources are the primary means of communication
between asynchronous computations
They can be composed in interesting ways.
For instance, map and filter are provided:
extension [T](s: Source[T])
def map[U](f: T => U): Source[U]
def filter(p: T => Boolean): Source[T]
Async.Source
Futures are a particular kind of an async source. (Other
implementations come from channels).
Async sources are the primary means of communication
between asynchronous computations
They can be composed in interesting ways.
For instance, map and filter are provided:
extension [T](s: Source[T])
def map[U](f: T => U): Source[U]
def filter(p: T => Boolean): Source[T]
Races
A race passes on the first of several sources:
def race[T](sources: Source[T]*): Source[T]
Higher-level operation:
def either[T1, T2](src1: Source[T1], src2: Source[T2])
: Source[Either[T, U]] =
race(
src1.map(Left(_)),
src2.map(Right(_))
)
Structured Concurrency
It’s now easy to implement zip and alt on futures:
extension [T](f1: Future[T])
def zip[U](f2: Future[U])(using Async): Future[(T, U)] =
Future:
await(either(f1, f2)) match
case Left(Success(x1)) => (x1, f2.value)
case Right(Success(x2)) => (f1.value, x2)
case Left(Failure(ex)) => throw ex
case Right(Failure(ex)) => throw ex
Structured Concurrency
It’s now easy to implement zip and alt on futures:
extension [T](f1: Future[T])
def alt(f2: Future[T])(using Async): Future[T] =
Future:
await(either(f1, f2)) match
case Left(Success(x1)) => x1
case Right(Success(x2)) => x2
case Left(_: Failure[?]) => f2.value
case Right(_: Failure[?]) => f1.value
Why Futures & Channels?
Futures: The simplest way to get parallelism
Define a computation
Run it in parallel
Await the result when needed
Channels: The canonical way of communication between
computations.
Both are instances as asynchronous sources
Why not Coroutines?
Often, coroutines (in the sense of CSP or goroutines) are used
instead of futures to work with channels.
But:
We need to be able to wait for a coroutine’s termination.
We need to handle any exceptions in the coroutine on the
outside
Both are achieved by using a Future[Unit].
So no different abstractions are needed.
Why an ErrorType Fixed to Try?
Natural solution if the language supports exception
But common complaint for current futures:
Error type is fixed to be Exception.
This makes it awkward to handle other errors.
For instance, how would you implement this function?
def acrobatics(xs: List[Future[Result[T, E]]])
: Future[Result[List[T], E]] =
Why an ErrorType Fixed to Try?
Natural solution if the language supports exception
But common complaint for current futures:
Error type is fixed to be Exception.
This makes it awkward to handle other errors.
For instance, how would you implement this function?
def acrobatics(xs: List[Future[Result[T, E]]])
: Future[Result[List[T], E]] =
Why an ErrorType Fixed to Try?
Natural solution if the language supports exception
But common complaint for current futures:
Error type is fixed to be Exception.
This makes it awkward to handle other errors.
For instance, how would you implement this function?
def acrobatics(xs: List[Future[Result[T, E]]])
: Future[Result[List[T], E]] =
Why an ErrorType Fixed to Try?
Natural solution if the language supports exception
But common complaint for current futures:
Error type is fixed to be Exception.
This makes it awkward to handle other errors.
New direct style abstractions don’t have that problem anymore!
def acrobatics(xs: List[Future[Result[T, E]]])
: Future[Result[List[T], E]] =
Future:
Result:
xs.map(_.value.?)
Simple compositions, no traverse or lift is needed.
Conclusion
Direct style has lots to offer
Suspensions can express every monad, but, provide more flexible
composition.
This gives completely new possibilities to express practical
foundations for concurrency and async I/O.
The future will be interesting…
Thank You
Conclusion
Direct style has lots to offer
Suspensions can express every monad, but, provide more flexible
composition.
This gives completely new possibilities to express practical
foundations for concurrency and async I/O.
The future will be interesting…
Thank You

More Related Content

What's hot

Functional programming
Functional programmingFunctional programming
Functional programming
ijcd
 
Chapter 06 constructors and destructors
Chapter 06 constructors and destructorsChapter 06 constructors and destructors
Chapter 06 constructors and destructors
Praveen M Jigajinni
 
OOP and FP
OOP and FPOOP and FP
OOP and FP
Mario Fusco
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...
Philip Schwarz
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
Philip Schwarz
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Philip Schwarz
 
Algebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain ModelsAlgebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain Models
Debasish Ghosh
 
Scala Intro
Scala IntroScala Intro
Java Generics - by Example
Java Generics - by ExampleJava Generics - by Example
Java Generics - by Example
CodeOps Technologies LLP
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Philip Schwarz
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
Mario Fusco
 
Lambda Expressions in Java
Lambda Expressions in JavaLambda Expressions in Java
Lambda Expressions in Java
Erhan Bagdemir
 
Izumi 1.0: Your Next Scala Stack
Izumi 1.0: Your Next Scala StackIzumi 1.0: Your Next Scala Stack
Izumi 1.0: Your Next Scala Stack
7mind
 
Iterator
IteratorIterator
Devoxx France 2023 - Les nouveautés de Java 19 et 20
Devoxx France 2023 - Les nouveautés de Java 19 et 20Devoxx France 2023 - Les nouveautés de Java 19 et 20
Devoxx France 2023 - Les nouveautés de Java 19 et 20
Jean-Michel Doudoux
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are Wrong
Mario Fusco
 
Java Presentation For Syntax
Java Presentation For SyntaxJava Presentation For Syntax
Java Presentation For Syntax
PravinYalameli
 
Functors, Applicatives and Monads In Scala
Functors, Applicatives and Monads In ScalaFunctors, Applicatives and Monads In Scala
Functors, Applicatives and Monads In Scala
Knoldus Inc.
 
Recursive Function
Recursive FunctionRecursive Function
Recursive Function
Kamal Acharya
 
Lambda Expressions in Java 8
Lambda Expressions in Java 8Lambda Expressions in Java 8
Lambda Expressions in Java 8
icarter09
 

What's hot (20)

Functional programming
Functional programmingFunctional programming
Functional programming
 
Chapter 06 constructors and destructors
Chapter 06 constructors and destructorsChapter 06 constructors and destructors
Chapter 06 constructors and destructors
 
OOP and FP
OOP and FPOOP and FP
OOP and FP
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
 
Algebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain ModelsAlgebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain Models
 
Scala Intro
Scala IntroScala Intro
Scala Intro
 
Java Generics - by Example
Java Generics - by ExampleJava Generics - by Example
Java Generics - by Example
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
 
Lambda Expressions in Java
Lambda Expressions in JavaLambda Expressions in Java
Lambda Expressions in Java
 
Izumi 1.0: Your Next Scala Stack
Izumi 1.0: Your Next Scala StackIzumi 1.0: Your Next Scala Stack
Izumi 1.0: Your Next Scala Stack
 
Iterator
IteratorIterator
Iterator
 
Devoxx France 2023 - Les nouveautés de Java 19 et 20
Devoxx France 2023 - Les nouveautés de Java 19 et 20Devoxx France 2023 - Les nouveautés de Java 19 et 20
Devoxx France 2023 - Les nouveautés de Java 19 et 20
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are Wrong
 
Java Presentation For Syntax
Java Presentation For SyntaxJava Presentation For Syntax
Java Presentation For Syntax
 
Functors, Applicatives and Monads In Scala
Functors, Applicatives and Monads In ScalaFunctors, Applicatives and Monads In Scala
Functors, Applicatives and Monads In Scala
 
Recursive Function
Recursive FunctionRecursive Function
Recursive Function
 
Lambda Expressions in Java 8
Lambda Expressions in Java 8Lambda Expressions in Java 8
Lambda Expressions in Java 8
 

Similar to scalar.pdf

Евгений Бурмако «scala.reflect»
Евгений Бурмако «scala.reflect»Евгений Бурмако «scala.reflect»
Евгений Бурмако «scala.reflect»
e-Legion
 
scala.reflect, Eugene Burmako
scala.reflect, Eugene Burmakoscala.reflect, Eugene Burmako
scala.reflect, Eugene Burmako
Vasil Remeniuk
 
A Survey of Concurrency Constructs
A Survey of Concurrency ConstructsA Survey of Concurrency Constructs
A Survey of Concurrency Constructs
Ted Leung
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009
Martin Odersky
 
Loops_in_Rv1.2b
Loops_in_Rv1.2bLoops_in_Rv1.2b
Loops_in_Rv1.2b
Carlo Fanara
 
Metaprogramming in Scala 2.10, Eugene Burmako,
Metaprogramming  in Scala 2.10, Eugene Burmako, Metaprogramming  in Scala 2.10, Eugene Burmako,
Metaprogramming in Scala 2.10, Eugene Burmako,
Vasil Remeniuk
 
Swift, swiftly
Swift, swiftlySwift, swiftly
Swift, swiftly
Jack Nutting
 
Lecture 5 interface.pdf
Lecture  5 interface.pdfLecture  5 interface.pdf
Lecture 5 interface.pdf
AdilAijaz3
 
Os Reindersfinal
Os ReindersfinalOs Reindersfinal
Os Reindersfinal
oscon2007
 
Os Reindersfinal
Os ReindersfinalOs Reindersfinal
Os Reindersfinal
oscon2007
 
Abstract Data Types (a) Explain briefly what is meant by the ter.pdf
Abstract Data Types (a) Explain briefly what is meant by the ter.pdfAbstract Data Types (a) Explain briefly what is meant by the ter.pdf
Abstract Data Types (a) Explain briefly what is meant by the ter.pdf
karymadelaneyrenne19
 
Devoxx
DevoxxDevoxx
ParaSail
ParaSail  ParaSail
ParaSail
AdaCore
 
Matlab Manual
Matlab ManualMatlab Manual
Fusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsFusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with Views
Philip Schwarz
 
Scala for Machine Learning
Scala for Machine LearningScala for Machine Learning
Scala for Machine Learning
Patrick Nicolas
 
Patterns in Python
Patterns in PythonPatterns in Python
Patterns in Python
dn
 
Intro to Scala
 Intro to Scala Intro to Scala
Intro to Scala
manaswinimysore
 
Guaranteeing Memory Safety in Rust
Guaranteeing Memory Safety in RustGuaranteeing Memory Safety in Rust
Guaranteeing Memory Safety in Rust
nikomatsakis
 
Fuel Up JavaScript with Functional Programming
Fuel Up JavaScript with Functional ProgrammingFuel Up JavaScript with Functional Programming
Fuel Up JavaScript with Functional Programming
Shine Xavier
 

Similar to scalar.pdf (20)

Евгений Бурмако «scala.reflect»
Евгений Бурмако «scala.reflect»Евгений Бурмако «scala.reflect»
Евгений Бурмако «scala.reflect»
 
scala.reflect, Eugene Burmako
scala.reflect, Eugene Burmakoscala.reflect, Eugene Burmako
scala.reflect, Eugene Burmako
 
A Survey of Concurrency Constructs
A Survey of Concurrency ConstructsA Survey of Concurrency Constructs
A Survey of Concurrency Constructs
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009
 
Loops_in_Rv1.2b
Loops_in_Rv1.2bLoops_in_Rv1.2b
Loops_in_Rv1.2b
 
Metaprogramming in Scala 2.10, Eugene Burmako,
Metaprogramming  in Scala 2.10, Eugene Burmako, Metaprogramming  in Scala 2.10, Eugene Burmako,
Metaprogramming in Scala 2.10, Eugene Burmako,
 
Swift, swiftly
Swift, swiftlySwift, swiftly
Swift, swiftly
 
Lecture 5 interface.pdf
Lecture  5 interface.pdfLecture  5 interface.pdf
Lecture 5 interface.pdf
 
Os Reindersfinal
Os ReindersfinalOs Reindersfinal
Os Reindersfinal
 
Os Reindersfinal
Os ReindersfinalOs Reindersfinal
Os Reindersfinal
 
Abstract Data Types (a) Explain briefly what is meant by the ter.pdf
Abstract Data Types (a) Explain briefly what is meant by the ter.pdfAbstract Data Types (a) Explain briefly what is meant by the ter.pdf
Abstract Data Types (a) Explain briefly what is meant by the ter.pdf
 
Devoxx
DevoxxDevoxx
Devoxx
 
ParaSail
ParaSail  ParaSail
ParaSail
 
Matlab Manual
Matlab ManualMatlab Manual
Matlab Manual
 
Fusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsFusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with Views
 
Scala for Machine Learning
Scala for Machine LearningScala for Machine Learning
Scala for Machine Learning
 
Patterns in Python
Patterns in PythonPatterns in Python
Patterns in Python
 
Intro to Scala
 Intro to Scala Intro to Scala
Intro to Scala
 
Guaranteeing Memory Safety in Rust
Guaranteeing Memory Safety in RustGuaranteeing Memory Safety in Rust
Guaranteeing Memory Safety in Rust
 
Fuel Up JavaScript with Functional Programming
Fuel Up JavaScript with Functional ProgrammingFuel Up JavaScript with Functional Programming
Fuel Up JavaScript with Functional Programming
 

More from Martin Odersky

Preparing for Scala 3
Preparing for Scala 3Preparing for Scala 3
Preparing for Scala 3
Martin Odersky
 
Simplicitly
SimplicitlySimplicitly
Simplicitly
Martin Odersky
 
What To Leave Implicit
What To Leave ImplicitWhat To Leave Implicit
What To Leave Implicit
Martin Odersky
 
What To Leave Implicit
What To Leave ImplicitWhat To Leave Implicit
What To Leave Implicit
Martin Odersky
 
From DOT to Dotty
From DOT to DottyFrom DOT to Dotty
From DOT to Dotty
Martin Odersky
 
Implementing Higher-Kinded Types in Dotty
Implementing Higher-Kinded Types in DottyImplementing Higher-Kinded Types in Dotty
Implementing Higher-Kinded Types in Dotty
Martin Odersky
 
Scala Days NYC 2016
Scala Days NYC 2016Scala Days NYC 2016
Scala Days NYC 2016
Martin Odersky
 
Compilers Are Databases
Compilers Are DatabasesCompilers Are Databases
Compilers Are Databases
Martin Odersky
 
Scala Days San Francisco
Scala Days San FranciscoScala Days San Francisco
Scala Days San Francisco
Martin Odersky
 
Scalax
ScalaxScalax
The Evolution of Scala
The Evolution of ScalaThe Evolution of Scala
The Evolution of Scala
Martin Odersky
 
Scala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationScala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentation
Martin Odersky
 
Flatmap
FlatmapFlatmap
flatMap Oslo presentation slides
flatMap Oslo presentation slidesflatMap Oslo presentation slides
flatMap Oslo presentation slides
Martin Odersky
 
Oscon keynote: Working hard to keep it simple
Oscon keynote: Working hard to keep it simpleOscon keynote: Working hard to keep it simple
Oscon keynote: Working hard to keep it simple
Martin Odersky
 
Scala eXchange opening
Scala eXchange openingScala eXchange opening
Scala eXchange opening
Martin Odersky
 

More from Martin Odersky (16)

Preparing for Scala 3
Preparing for Scala 3Preparing for Scala 3
Preparing for Scala 3
 
Simplicitly
SimplicitlySimplicitly
Simplicitly
 
What To Leave Implicit
What To Leave ImplicitWhat To Leave Implicit
What To Leave Implicit
 
What To Leave Implicit
What To Leave ImplicitWhat To Leave Implicit
What To Leave Implicit
 
From DOT to Dotty
From DOT to DottyFrom DOT to Dotty
From DOT to Dotty
 
Implementing Higher-Kinded Types in Dotty
Implementing Higher-Kinded Types in DottyImplementing Higher-Kinded Types in Dotty
Implementing Higher-Kinded Types in Dotty
 
Scala Days NYC 2016
Scala Days NYC 2016Scala Days NYC 2016
Scala Days NYC 2016
 
Compilers Are Databases
Compilers Are DatabasesCompilers Are Databases
Compilers Are Databases
 
Scala Days San Francisco
Scala Days San FranciscoScala Days San Francisco
Scala Days San Francisco
 
Scalax
ScalaxScalax
Scalax
 
The Evolution of Scala
The Evolution of ScalaThe Evolution of Scala
The Evolution of Scala
 
Scala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationScala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentation
 
Flatmap
FlatmapFlatmap
Flatmap
 
flatMap Oslo presentation slides
flatMap Oslo presentation slidesflatMap Oslo presentation slides
flatMap Oslo presentation slides
 
Oscon keynote: Working hard to keep it simple
Oscon keynote: Working hard to keep it simpleOscon keynote: Working hard to keep it simple
Oscon keynote: Working hard to keep it simple
 
Scala eXchange opening
Scala eXchange openingScala eXchange opening
Scala eXchange opening
 

Recently uploaded

🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
campbellclarkson
 
What is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdfWhat is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdf
kalichargn70th171
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
Maitrey Patel
 
Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...
Paul Brebner
 
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
kgyxske
 
The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024
Yara Milbes
 
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
Luigi Fugaro
 
Voxxed Days Trieste 2024 - Unleashing the Power of Vector Search and Semantic...
Voxxed Days Trieste 2024 - Unleashing the Power of Vector Search and Semantic...Voxxed Days Trieste 2024 - Unleashing the Power of Vector Search and Semantic...
Voxxed Days Trieste 2024 - Unleashing the Power of Vector Search and Semantic...
Luigi Fugaro
 
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdfBaha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid
 
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
kalichargn70th171
 
Alluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio Webinar | 10x Faster Trino Queries on Your Data PlatformAlluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio, Inc.
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
gapen1
 
The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...
The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...
The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...
kalichargn70th171
 
Beginner's Guide to Observability@Devoxx PL 2024
Beginner's  Guide to Observability@Devoxx PL 2024Beginner's  Guide to Observability@Devoxx PL 2024
Beginner's Guide to Observability@Devoxx PL 2024
michniczscribd
 
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdfThe Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
kalichargn70th171
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Paul Brebner
 
Assure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyesAssure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
ppt on the brain chip neuralink.pptx
ppt  on   the brain  chip neuralink.pptxppt  on   the brain  chip neuralink.pptx
ppt on the brain chip neuralink.pptx
Reetu63
 
All you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVMAll you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVM
Alina Yurenko
 
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom KittEnhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Peter Caitens
 

Recently uploaded (20)

🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
 
What is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdfWhat is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdf
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
 
Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...
 
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
 
The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024
 
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
 
Voxxed Days Trieste 2024 - Unleashing the Power of Vector Search and Semantic...
Voxxed Days Trieste 2024 - Unleashing the Power of Vector Search and Semantic...Voxxed Days Trieste 2024 - Unleashing the Power of Vector Search and Semantic...
Voxxed Days Trieste 2024 - Unleashing the Power of Vector Search and Semantic...
 
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdfBaha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
 
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
 
Alluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio Webinar | 10x Faster Trino Queries on Your Data PlatformAlluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio Webinar | 10x Faster Trino Queries on Your Data Platform
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
 
The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...
The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...
The Power of Visual Regression Testing_ Why It Is Critical for Enterprise App...
 
Beginner's Guide to Observability@Devoxx PL 2024
Beginner's  Guide to Observability@Devoxx PL 2024Beginner's  Guide to Observability@Devoxx PL 2024
Beginner's Guide to Observability@Devoxx PL 2024
 
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdfThe Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
 
Assure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyesAssure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyes
 
ppt on the brain chip neuralink.pptx
ppt  on   the brain  chip neuralink.pptxppt  on   the brain  chip neuralink.pptx
ppt on the brain chip neuralink.pptx
 
All you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVMAll you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVM
 
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom KittEnhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
 

scalar.pdf

  • 1. Direct Style Scala Martin Odersky EPFL Scalar Conference March 24, 2023
  • 2. Shifting Foundations Trends Widespread support for async/await Runtimes get better support for fibers or continuations. Examples Goroutines, Project Loom in Java, Kotlin coroutines, OCaml or Haskell delimited continuations, Research languages such as Effekt, Koka Thesis of this talk This will deeply influence libraries and frameworks It’s very attractive now to go back to direct style.
  • 3. Shifting Foundations Trends Widespread support for async/await Runtimes get better support for fibers or continuations. Examples Goroutines, Project Loom in Java, Kotlin coroutines, OCaml or Haskell delimited continuations, Research languages such as Effekt, Koka Thesis of this talk This will deeply influence libraries and frameworks It’s very attractive now to go back to direct style.
  • 4. How will this influence Scala in the future? 1 There will likely be native foundations for direct-style reactive programming Delimited continuations on Scala Native Fibers on latest Java Source or bytecode rewriting for older Java, JS 2 This will enable new techniques for designing and composing software 3 There will be a move away from monads as the primary way of code composition.
  • 5. Building a Direct-Style Stack First step: Boundary/break Error handling Suspensions Concurrency library design built on that
  • 6. Building a Direct-Style Stack First step: Boundary/break (shipped) Error handling (enabled) Suspensions (wip) Concurrency library design built on that (wip)
  • 7. Warmup: Boundary/break A cleaner alternative to non-local returns (which will go away) def firstIndex[T](xs: List[T], elem: T): Int = boundary: for (x, i) <- xs.zipWithIndex do if x == elem then break(i) -1 boundary establishes a boundary break returns with a value from it.
  • 9. API package scala.util object boundary: final class Label[-T] def break[T](value: T)(using label: Label[T]): Nothing = throw Break(label, value) inline def apply[T](inline body: Label[T] ?=> T): T = ... end boundary To break, you need a label that represents the boundary. In a sense, label is a capability that enables to break. (This is a common pattern)
  • 10. Implementation The implementation of break produces efficient code. If break appears in the same stackframe as its boundary, use a jump. Otherwise use a fast exception that does not capture a stack trace. A stack trace is not needed since we know the exception will be handled (*) (*) To be 100% sure, this needs capture checking.
  • 11. Implementation The implementation of break produces efficient code. If break appears in the same stackframe as its boundary, use a jump. Otherwise use a fast exception that does not capture a stack trace. A stack trace is not needed since we know the exception will be handled (*) (*) To be 100% sure, this needs capture checking.
  • 12. Stage 2: Error handling boundary/break can be used as the basis for flexible error handling. For instance: def firstColumn[T](xss: List[List[T]]): Option[List[T]] = optional: xss.map(_.headOption.?) Optionally, returns the first column of the matrix xss. Returns None if there is an empty row.
  • 13. Error handling implementation optional and ? on options can be implemented quite easily on top of boundary/break: object optional: inline def apply[T](inline body: Label[None.type] ?=> T) : Option[T] = boundary(Some(body)) extension [T](r: Option[T]) inline def ? (using label: Label[None.type]): T = r match case Some(x) => x case None => break(None) Analogous implementations are possible for other result types such as Either or a Rust-like Result. My ideal way of error handling would be based on Result + ?.
  • 14. Stage 3: Suspensions Question: What if we could store the stack segment between a break and its boundary and re-use it at some later time?
  • 15. Suspensions Question: What if we could store the stack segment between a break and its boundary and re-use it at some later time? This is the idea of delimited continuations.
  • 16. Suspensions Question: What if we could store the stack segment between a break and its boundary and re-use it at some later time? This is the idea of delimited continuations.
  • 17. Suspension API class Suspension[-T, +R]: def resume(arg: T): R = ??? def suspend[T, R](body: Suspension[T, R] => R)(using Label[R]): T Suspensions are quite powerful. They can express at the same time algebraic effects and monads.
  • 18. Generators Python-style generators are a simple example of algebraic effects. def example = Generator: produce(”We’ll give you all the numbers divisible by 3 or 2”) for i <- 1 to 1000 do if i % 3 == 0 then produce(s”$i is divisible by 3”) else if i % 2 == 0 then produce(s”$i is even”) Here, Generator is essentially a simplified Iterator trait Generator[T]: def nextOption: Option[T]
  • 19. Algebraic Effects Task: Build a generate implementation of Generator, so that one can compute the leafs of a Tree like this: enum Tree[T]: case Leaf(x: T) case Inner(xs: List[Tree[T]]) def leafs[T](t: Tree[T]): Generator[T] = generate: // effect scope def recur(t: Tree[T]): Unit = t match case Tree.Leaf(x) => produce(x) // effect case Tree.Inner(xs) => xs.foreach(recur) recur(t)
  • 20. Generator Implementation trait Produce[-T]: def produce(x: T): Unit def generate[T](body: Produce[T] ?=> Unit) = new Generator[T]: def nextOption: Option[T] = step() var step: () => Option[T] =
  • 21. The Step Function trait Produce[-T]: // effect type def produce(x: T): Unit def generate[T](body: Produce[T] ?=> Unit) = new Generator[T]: def nextOption: Option[T] = step() var step: () => Option[T] = () => boundary: given Produce[T] with // handler def produce(x: T): Unit = suspend[Unit, Option[T]]: k => step = () => k.resume(()) Some(x) body None
  • 22. Summary: Algebraic Effects Effects are methods of effect traits Handlers are implementations of effect traits They are passed as implicit parameters. They can abort part of a computation via break They can also suspend part of a computation as a continuation and resume it later.
  • 23. Implementing Suspensions There are several possibilities: Directly in the runtime, as shown in the designs On top of fibers (requires some compromises) By bytecode rewriting (e.g. Quasar, javactrl) By source rewriting
  • 24. Suspensions and Monads: Wadler (1993): Continuations can be expressed as a monad. “Haskell is the essence of ML” Filinski (1994): Every monad can be expressed in direct style using just delimited continuations. “ML is the essence of Haskell” My take: designs based on continuations are simpler to compose than monads.
  • 25. Suspensions and Monads: Wadler (1993): Continuations can be expressed as a monad. “Haskell is the essence of ML” Filinski (1994): Every monad can be expressed in direct style using just delimited continuations. “ML is the essence of Haskell” My take: designs based on continuations are simpler to compose than monads.
  • 26. Direct-Style Futures With suspend(*), we can implement lightweight and universal await construct that can be called anywhere. This can express simple, direct-style futures. val sum = Future: val f1 = Future(c1.read) val f2 = Future(c2.read) f1.value + f2.value Structured concurrency: Local futures f1 and f2 complete before sum completes. This might mean that one of them is cancelled if the other returns with a failure. (*) Loom-like fibers would work as well.
  • 27. Compare with Status Quo val sum = val f1 = Future(c1.read) val f2 = Future(c2.read) for x <- f1 y <- f2 yield x + y Composition of futures is monadic but creation isn’t, which is a bit awkward.
  • 28. A Strawman lampepfl/async is an early stage prototype of a modern, low-level concurrency library in direct style. Main elements Futures: the primary active elements Channels: the primary passive elements Async Sources Futures and Channels both implement a new fundamental abstraction: an asynchronous source. Async Contexts An async context is a capability that allows a computation to suspend while waiting for the result of an async source. Link: github.com/lampepfl/async
  • 29. Futures The Future trait is defined as follows: trait Future[+T] extends Async.Source[Try[T]], Cancellable: def result(using Async): Try[T] def value(using Async): T = result.get The result method can be defined like this: def result(using async: Async): T = async.await(this) async is a capability that allows to suspend in an await method.
  • 30. Futures The Future trait is defined as follows: trait Future[+T] extends Async.Source[Try[T]], Cancellable: def result(using Async): Try[T] def value(using Async): T = result.get The result method can be defined like this: def result(using async: Async): T = async.await(this) async is a capability that allows to suspend in an await method.
  • 31. Async The Async trait is defined as follows: trait Async: def await[T](src: Async.Source[T]): T def scheduler: ExecutionContext def group: CancellationGroup def withGroup(group: CancellationGroup): Async await gets the (first) element of an Async.Source. It suspends if necessary.
  • 32. Async.Source Futures are a particular kind of an async source. (Other implementations come from channels). Async sources are the primary means of communication between asynchronous computations They can be composed in interesting ways. For instance, map and filter are provided: extension [T](s: Source[T]) def map[U](f: T => U): Source[U] def filter(p: T => Boolean): Source[T]
  • 33. Async.Source Futures are a particular kind of an async source. (Other implementations come from channels). Async sources are the primary means of communication between asynchronous computations They can be composed in interesting ways. For instance, map and filter are provided: extension [T](s: Source[T]) def map[U](f: T => U): Source[U] def filter(p: T => Boolean): Source[T]
  • 34. Races A race passes on the first of several sources: def race[T](sources: Source[T]*): Source[T] Higher-level operation: def either[T1, T2](src1: Source[T1], src2: Source[T2]) : Source[Either[T, U]] = race( src1.map(Left(_)), src2.map(Right(_)) )
  • 35. Structured Concurrency It’s now easy to implement zip and alt on futures: extension [T](f1: Future[T]) def zip[U](f2: Future[U])(using Async): Future[(T, U)] = Future: await(either(f1, f2)) match case Left(Success(x1)) => (x1, f2.value) case Right(Success(x2)) => (f1.value, x2) case Left(Failure(ex)) => throw ex case Right(Failure(ex)) => throw ex
  • 36. Structured Concurrency It’s now easy to implement zip and alt on futures: extension [T](f1: Future[T]) def alt(f2: Future[T])(using Async): Future[T] = Future: await(either(f1, f2)) match case Left(Success(x1)) => x1 case Right(Success(x2)) => x2 case Left(_: Failure[?]) => f2.value case Right(_: Failure[?]) => f1.value
  • 37. Why Futures & Channels? Futures: The simplest way to get parallelism Define a computation Run it in parallel Await the result when needed Channels: The canonical way of communication between computations. Both are instances as asynchronous sources
  • 38. Why not Coroutines? Often, coroutines (in the sense of CSP or goroutines) are used instead of futures to work with channels. But: We need to be able to wait for a coroutine’s termination. We need to handle any exceptions in the coroutine on the outside Both are achieved by using a Future[Unit]. So no different abstractions are needed.
  • 39. Why an ErrorType Fixed to Try? Natural solution if the language supports exception But common complaint for current futures: Error type is fixed to be Exception. This makes it awkward to handle other errors. For instance, how would you implement this function? def acrobatics(xs: List[Future[Result[T, E]]]) : Future[Result[List[T], E]] =
  • 40. Why an ErrorType Fixed to Try? Natural solution if the language supports exception But common complaint for current futures: Error type is fixed to be Exception. This makes it awkward to handle other errors. For instance, how would you implement this function? def acrobatics(xs: List[Future[Result[T, E]]]) : Future[Result[List[T], E]] =
  • 41. Why an ErrorType Fixed to Try? Natural solution if the language supports exception But common complaint for current futures: Error type is fixed to be Exception. This makes it awkward to handle other errors. For instance, how would you implement this function? def acrobatics(xs: List[Future[Result[T, E]]]) : Future[Result[List[T], E]] =
  • 42. Why an ErrorType Fixed to Try? Natural solution if the language supports exception But common complaint for current futures: Error type is fixed to be Exception. This makes it awkward to handle other errors. New direct style abstractions don’t have that problem anymore! def acrobatics(xs: List[Future[Result[T, E]]]) : Future[Result[List[T], E]] = Future: Result: xs.map(_.value.?) Simple compositions, no traverse or lift is needed.
  • 43. Conclusion Direct style has lots to offer Suspensions can express every monad, but, provide more flexible composition. This gives completely new possibilities to express practical foundations for concurrency and async I/O. The future will be interesting… Thank You
  • 44. Conclusion Direct style has lots to offer Suspensions can express every monad, but, provide more flexible composition. This gives completely new possibilities to express practical foundations for concurrency and async I/O. The future will be interesting… Thank You