Skip to content

Commit 55a56c6

Browse files
authored
Update AsyncSeqExamples.fsx
1 parent 1023d8a commit 55a56c6

1 file changed

Lines changed: 9 additions & 66 deletions

File tree

docs/AsyncSeqExamples.fsx

Lines changed: 9 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#r "nuget: FSharp.Control.AsyncSeq,{{package-version}}"
1212
#endif // IPYNB
1313

14-
1514
(**
1615
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/fsprojects/FSharp.Control.AsyncSeq/gh-pages?filepath=AsyncSeqExamples.ipynb)
1716
@@ -23,30 +22,23 @@
2322
open System
2423
open FSharp.Control
2524

26-
2725
(**
2826
2927
## Group By
3028
3129
`AsyncSeq.groupBy` partitions an input sequence into sub-sequences with respect to the specified `projection` function. This operation is the asynchronous analog to `Seq.groupBy`.
3230
33-
3431
### Example Execution
3532
3633
An example execution can be depicted visually as follows:
3734
35+
```
3836
--------------------------------------------------
3937
| source | a0 | a2 | a3 | a4 | a5 | |
4038
| key | k1 | k2 | k1 | k3 | | |
4139
| result | k1 * [a1,a3] | k2 * [a2] | k3 * [a4] |
4240
--------------------------------------------------
43-
44-
45-
46-
a0
47-
k0
48-
49-
41+
```
5042
5143
### Use Case
5244
@@ -69,7 +61,6 @@ let action (e:Event) : Async<unit> =
6961
stream
7062
|> AsyncSeq.iterAsync action
7163

72-
7364
(**
7465
7566
The above workflow will read an event from the stream, perform an operation and then read the next event.
@@ -104,7 +95,6 @@ let batchStream : AsyncSeq<Event[]> =
10495
let batchAction (es:Event[]) : Async<unit> =
10596
failwith "undefined"
10697

107-
10898
(**
10999
110100
Ordering is still important. For example, the batch action could write events into a full-text search index. We would like the full-text search index to be sequentially consistent. As such, the events need to be applied in the order they were emitted. The following workflow has the desired properties:
@@ -119,7 +109,6 @@ batchStream
119109
>> AsyncSeq.iterAsync batchAction) // perform the batch operation
120110
|> AsyncSeq.iter ignore
121111

122-
123112
(**
124113
125114
The above workflow:
@@ -130,14 +119,6 @@ The above workflow:
130119
4. Buffers elements of each sub-sequence by time and space.
131120
5. Processes the sub-sequences in parallel, but individual sub-sequences sequentially.
132121
133-
---
134-
135-
*)
136-
137-
138-
139-
(**
140-
141122
## Merge
142123
143124
`AsyncSeq.merge` non-deterministically merges two async sequences into one. It is non-deterministic in the sense that the resulting sequence emits elements whenever *either* input sequence emits a value. Since it isn't always known which will emit a value first, if at all, the operation is non-deterministic. This operation is in contrast to `AsyncSeq.zip` which also takes two async sequences and returns a single async sequence, but as opposed to emitting an element when *either* input sequence produces a value, it emits an element when *both* sequences emit a value. This operation is also in contrast to `AsyncSeq.append` which concatenates two async sequences, emitting all element of one, followed by all elements of the another.
@@ -146,17 +127,18 @@ The above workflow:
146127
147128
An example execution can be depicted visually as follows:
148129
130+
```
149131
-----------------------------------------
150132
| source1 | t0 | | t1 | | | t2 |
151133
| source2 | | u0 | | | u1 | |
152134
| result | t0 | u0 | t1 | | u1 | t2 |
153135
-----------------------------------------
136+
```
154137
155138
### Use Case
156139
157140
Suppose you wish to perform an operation when either of two async sequences emits an element. One way to do this is two start consuming both async sequences in parallel. If we would like to perform only one operation at a time, we can use `AsyncSeq.merge` as follows:
158-
159-
```
141+
*)
160142

161143
/// Represents an stream emitting elements on a specified interval.
162144
let intervalMs (periodMs:int) = asyncSeq {
@@ -168,18 +150,10 @@ let intervalMs (periodMs:int) = asyncSeq {
168150
let either : AsyncSeq<DateTime> =
169151
AsyncSeq.merge (intervalMs 20) (intervalMs 30)
170152

171-
The sequence `either` emits an element every 20ms and every 30ms.
172-
173-
```
174-
175-
---
176-
177-
*)
178-
179-
180-
181153
(**
182154
155+
The sequence `either` emits an element every 20ms and every 30ms.
156+
183157
## Combine Latest
184158
185159
@@ -202,7 +176,6 @@ c0 = f a0 b0
202176
c1 = f a0 b1
203177
c2 = f a1 b1
204178
c3 = f a2 b1
205-
206179
```
207180
208181
### Use Case
@@ -257,15 +230,6 @@ let changesOrInterval : AsyncSeq<Value> =
257230
258231
We can now consume this async sequence and use it to trigger downstream operations, such as updating the configuration of a running program, in flight.
259232
260-
---
261-
262-
*)
263-
264-
265-
266-
267-
268-
(**
269233
270234
## Distinct Until Changed
271235
@@ -275,10 +239,12 @@ We can now consume this async sequence and use it to trigger downstream operatio
275239
276240
An example execution can be visualized as follows:
277241
242+
```
278243
-----------------------------------
279244
| source | a | a | b | b | b | a |
280245
| result | a | | b | | | a |
281246
-----------------------------------
247+
```
282248
283249
### Use Case
284250
@@ -327,13 +293,6 @@ let result : Async<string> =
327293
if st.finished then Some st.result
328294
else None)
329295

330-
(**
331-
332-
---
333-
334-
*)
335-
336-
337296
(**
338297
339298
## Zip
@@ -374,13 +333,6 @@ let eventsAtLeastOneSec =
374333
375334
The resulting async sequence `eventsAtLeastOneSec` will emit an element at-most every second. Note that the input sequence of timeouts is infinite - this is to allow the other sequence to have any length since `AsyncSeq.zipWith` will terminate when either input sequence terminates.
376335
377-
*)
378-
379-
380-
381-
382-
(**
383-
384336
## Buffer by Time and Count
385337
386338
`AsyncSeq.bufferByTimeAndCount` consumes the input sequence until a specified number of elements are consumed or a timeout expires at which point the resulting sequence emits the buffered of elements, unless no elements have been buffered. It is similar to `AsyncSeq.bufferByCount` but allows a buffer to be emitted base on a timeout in addition to buffer size. Both are useful for batching inputs before performing an operation. `AsyncSeq.bufferByTimeAndCount` allows an async workflow to proceed even if there are no inputs received during a certain time period.
@@ -397,9 +349,6 @@ An example execution can be visually depicted as follows:
397349
```
398350
The last event `a4` is emitted after a timeout.
399351
400-
401-
402-
403352
### Use Case
404353
405354
Suppose we're writing a service which consumes a stream of events and indexes them into full-text search index. We can index each event one by one, however we get a performance improvement if we buffer events into small batches. We can buffer into fixed size batches using `AsyncSeq.bufferByCount`. However, the source event stream may stop emitting events half way through a batch which would leave those events in the buffer until more events arrive. `AsyncSeq.bufferByTimeAndCount` allows the async workflow to make progress by imposing a bound on how long a non-empty but incomplete buffer can wait more additional items.
@@ -415,9 +364,3 @@ let bufferTimeout = 1000
415364
let bufferedEvents : AsyncSeq<Event[]> =
416365
events |> AsyncSeq.bufferByCountAndTime bufferSize bufferTimeout
417366

418-
419-
420-
421-
422-
423-

0 commit comments

Comments
 (0)