11# scala-async [ ![ Build Status] ( https://travis-ci.org/scala/scala-async.svg?branch=master )] ( https://travis-ci.org/scala/scala-async ) [ <img src =" https://img.shields.io/maven-central/v/org.scala-lang.modules/scala-async_2.12.svg?label=latest%20release%20for%202.12 " >] ( http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-async_2.12 ) [ <img src =" https://img.shields.io/maven-central/v/org.scala-lang.modules/scala-async_2.13.svg?label=latest%20release%20for%202.13 " >] ( http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-async_2.13 )
22
3- ## Supported Scala versions
4-
5- This branch (version series 0.10.x) targets Scala 2.12 and 2.13. ` scala-async ` is no longer maintained for older versions.
3+ A DSL to enable a direct style of programming with when composing values wrapped in Scala ` Future ` s.
64
75## Quick start
86
97To include scala-async in an existing project use the library published on Maven Central.
108For sbt projects add the following to your build definition - build.sbt or project/Build.scala:
119
10+ ### Use a modern Scala compiler
11+
12+ As of scala-async 1.0, Scala 2.12.12+ or 2.13.3+ are required.
13+
14+ ### Add dependency
15+
16+ #### SBT Example
17+
1218``` scala
1319libraryDependencies += " org.scala-lang.modules" %% " scala-async" % " 0.10.0"
1420libraryDependencies += " org.scala-lang" % " scala-reflect" % scalaVersion.value % Provided
@@ -17,28 +23,58 @@ libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value %
1723For Maven projects add the following to your <dependencies > (make sure to use the correct Scala version suffix
1824to match your project’s Scala binary version):
1925
26+ #### Maven Example
27+
2028``` scala
2129<dependency >
22- <groupId >org.scala- lang.modules</groupId >
23- <artifactId >scala- async_2.12 </artifactId >
24- <version >0.10 .0 </version >
30+ <groupId >org.scala- lang.modules</groupId >
31+ <artifactId >scala- async_2.13 </artifactId >
32+ <version >1.0 .0 </version >
2533</dependency >
2634<dependency >
27- <groupId >org.scala- lang</groupId >
28- <artifactId >scala- reflect</artifactId >
29- <version >2.12.11 </version >
30- <scope >provided</scope >
35+ <groupId >org.scala- lang</groupId >
36+ <artifactId >scala- reflect</artifactId >
37+ <version >2.13.3 </version >
38+ <scope >provided</scope >
3139</dependency >
3240```
3341
34- After adding scala-async to your classpath, write your first ` async ` block:
42+ ### Enable compiler support for ` async `
43+
44+ Add the ` -Xasync ` to the Scala compiler options.
45+
46+ #### SBT Example
47+ ``` scala
48+ scalaOptions += " -Xasync"
49+ ```
50+
51+ #### Maven Example
52+
53+ ``` xml
54+ <project >
55+ ...
56+ <plugin >
57+ <groupId >net.alchim31.maven</groupId >
58+ <artifactId >scala-maven-plugin</artifactId >
59+ <version >4.4.0</version >
60+ <configuration >
61+ <args >
62+ <arg >-Xasync</arg >
63+ </args >
64+ </configuration >
65+ </plugin >
66+ ...
67+ </project >
68+ ```
69+
70+ ### Start coding
3571
3672``` scala
3773import scala .concurrent .ExecutionContext .Implicits .global
3874import scala .async .Async .{async , await }
3975
4076val future = async {
41- val f1 = async { ...; true }
77+ val f1 : Future [ Boolean ] = async { ...; true }
4278 val f2 = async { ...; 42 }
4379 if (await(f1)) await(f2) else 0
4480}
@@ -93,6 +129,22 @@ def combined: Future[Int] = async {
93129}
94130```
95131
132+ ## Limitations
133+
134+ ### ` await ` must be directly in the control flow of the async expression
135+
136+ The ` await ` cannot be nested under a local method, object, class or lambda:
137+
138+ ```
139+ async {
140+ List(1).foreach { x => await(f(x) } // invali
141+ }
142+ ```
143+
144+ ### ` await ` must be not be nested within ` try ` / ` catch ` / ` finally ` .
145+
146+ This implementation restriction may be lifted in future versions.
147+
96148## Comparison with direct use of ` Future ` API
97149
98150This computation could also be expressed by directly using the
@@ -119,53 +171,3 @@ The `async` approach has two advantages over the use of
119171 required at each generator (` <- ` ) in the for-comprehension.
120172 This reduces the size of generated code, and can avoid boxing
121173 of intermediate results.
122-
123- ## Comparison with CPS plugin
124-
125- The existing continuations (CPS) plugin for Scala can also be used
126- to provide a syntactic layer like ` async ` . This approach has been
127- used in Akka's [ Dataflow Concurrency] ( http://doc.akka.io/docs/akka/2.3-M1/scala/dataflow.html )
128- (now deprecated in favour of this library).
129-
130- CPS-based rewriting of asynchronous code also produces a closure
131- for each suspension. It can also lead to type errors that are
132- difficult to understand.
133-
134- ## How it works
135-
136- - The ` async ` macro analyses the block of code, looking for control
137- structures and locations of ` await ` calls. It then breaks the code
138- into 'chunks'. Each chunk contains a linear sequence of statements
139- that concludes with a branching decision, or with the registration
140- of a subsequent state handler as the continuation.
141- - Before this analysis and transformation, the program is normalized
142- into a form amenable to this manipulation. This is called the
143- "A Normal Form" (ANF), and roughly means that:
144- - ` if ` and ` match ` constructs are only used as statements;
145- they cannot be used as an expression.
146- - calls to ` await ` are not allowed in compound expressions.
147- - Identify vals, vars and defs that are accessed from multiple
148- states. These will be lifted out to fields in the state machine
149- object.
150- - Synthesize a class that holds:
151- - an integer representing the current state ID.
152- - the lifted definitions.
153- - an ` apply(value: Try[Any]): Unit ` method that will be
154- called on completion of each future. The behavior of
155- this method is determined by the current state. It records
156- the downcast result of the future in a field, and calls the
157- ` resume() ` method.
158- - the ` resume(): Unit ` method that switches on the current state
159- and runs the users code for one 'chunk', and either:
160- a) registers the state machine as the handler for the next future
161- b) completes the result Promise of the ` async ` block, if at the terminal state.
162- - an ` apply(): Unit ` method that starts the computation.
163-
164- ## Limitations
165-
166- - See the [ neg] ( https://github.com/scala/async/tree/master/src/test/scala/scala/async/neg ) test cases
167- for constructs that are not allowed in an ` async ` block.
168- - See the [ issue list] ( https://github.com/scala/async/issues?state=open ) for which of these restrictions are planned
169- to be dropped in the future.
170- - See [ #32 ] ( https://github.com/scala/async/issues/32 ) for why ` await ` is not possible in closures, and for suggestions on
171- ways to structure the code to work around this limitation.
0 commit comments