Skip to content

Commit eeb70f8

Browse files
committed
Simplify and update README
1 parent 47e27a0 commit eeb70f8

File tree

1 file changed

+16
-50
lines changed

1 file changed

+16
-50
lines changed

README.md

+16-50
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,22 @@ def combined: Future[Int] = async {
9393
}
9494
```
9595

96+
## Limitations
97+
98+
### `await` must be directly in the control flow of the async expression
99+
100+
The `await` cannot be nested under a local method, object, class or lambda:
101+
102+
```
103+
async {
104+
List(1).foreach { x => await(f(x) } // invali
105+
}
106+
```
107+
108+
### `await` must be not be nested within `try` / `catch` / `finally`.
109+
110+
This implementation restriction may be lifted in future versions.
111+
96112
## Comparison with direct use of `Future` API
97113

98114
This computation could also be expressed by directly using the
@@ -119,53 +135,3 @@ The `async` approach has two advantages over the use of
119135
required at each generator (`<-`) in the for-comprehension.
120136
This reduces the size of generated code, and can avoid boxing
121137
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

Comments
 (0)