Skip to content

Commit fb986ef

Browse files
committed
Update readme.md and release notes
1 parent 0f78665 commit fb986ef

File tree

2 files changed

+25
-16
lines changed

2 files changed

+25
-16
lines changed

README.md

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ See [release notes.txt](release-notes.txt) for the version history of `TaskSeq`.
5151

5252
## Overview
5353

54-
The `IAsyncEnumerable` interface was added to .NET in `.NET Core 3.0` and is part of `.NET Standard 2.1`. The main use-case was for iterative asynchronous enumeration over some resource. For instance, an event stream or a REST API interface with pagination, asynchronous reading over a list of files and accumulating the results, where each action can be modeled as a [`MoveNextAsync`][4] call on the [`IAsyncEnumerator<'T>`][5] given by a call to [`GetAsyncEnumerator()`][6].
54+
The `IAsyncEnumerable` interface was added to .NET in `.NET Core 3.0` and is part of `.NET Standard 2.1`. The main use-case was for iterative asynchronous enumeration over some resource. For instance, an event stream or a REST API interface with pagination, asynchronous reading over a list of files and accumulating the results, where each action can be modeled as a [`MoveNextAsync`][4] call on the [`IAsyncEnumerator<'T>`][3] given by a call to [`GetAsyncEnumerator()`][6].
5555

5656
Since the introduction of `task` in F# the call for a native implementation of _task sequences_ has grown, in particular because proper iteration over an `IAsyncEnumerable` has proven challenging, especially if one wants to avoid mutable variables. This library is an answer to that call and applies the same _resumable state machine_ approach with `taskSeq`.
5757

@@ -177,23 +177,28 @@ There are more differences:
177177
| | `TaskSeq` | `AsyncSeq` |
178178
|----------------------------|---------------------------------------------------------------------------------|----------------------------------------------------------------------|
179179
| **Frameworks** | .NET 5.0+, NetStandard 2.1 | .NET 5.0+, NetStandard 2.0 and 2.1, .NET Framework 4.6.1+ |
180-
| **Underlying type** | `System.Collections.Generic.IAsyncEnumerable<'T>` | Its own type, also called `IAsyncEnumerable<'T>`, but not compatible |
180+
| **F# concept of** | `task` | `async` |
181+
| **Underlying type** | [`Generic.IAsyncEnumerable<'T>`][3] <sup>[note #1](#tsnote1 "Full name System.Collections.Generic.IAsyncEnumerable&lt;'T>.")</sup>| Its own type, also called `IAsyncEnumerable<'T>`<sup>[note #1](#tsnote1 "Full name FSharp.Control.IAsyncEnumerable&lt;'T>.")</sup> |
181182
| **Implementation** | State machine (statically compiled) | No state machine, continuation style |
182183
| **Semantics** | `seq`-like: on-demand | `seq`-like: on-demand |
184+
| **Disposability** | Asynchronous, through [`IAsyncDisposable`][7] | Synchronous, through `IDisposable` |
183185
| **Support `let!`** | All `task`-like: `Async<'T>`, `Task<'T>`, `ValueTask<'T>` or any `GetAwaiter()` | `Async<'T>` only |
184186
| **Support `do!`** | `Async<unit>`, `Task<unit>` and `Task`, `ValueTask<unit>` and `ValueTask` | `Async<unit>` only |
185-
| **Support `yield!`** | `IAsyncEnumerable<'T>`, `AsyncSeq`, any sequence | `AsyncSeq` |
186-
| **Support `for`** | `IAsyncEnumerable<'T>`, `AsyncSeq`, any sequence | `AsyncSeq`, any sequence |
187+
| **Support `yield!`** | [`IAsyncEnumerable<'T>`][3] (= `TaskSeq`), `AsyncSeq`, any sequence | `AsyncSeq` |
188+
| **Support `for`** | [`IAsyncEnumerable<'T>`][3] (= `TaskSeq`), `AsyncSeq`, any sequence | `AsyncSeq`, any sequence |
187189
| **Behavior with `yield`** | Zero allocations; no `Task` or even `ValueTask` created | Allocates an F# `Async` wrapped in a singleton `AsyncSeq` |
188-
| **Conversion to other** | `TaskSeq.toAsyncSeq` | `AsyncSeq.toAsyncEnum` |
189-
| **Conversion from other** | Implicit (`yield!`) or `TaskSeq.ofAsyncSeq` | `AsyncSeq.ofAsyncEnum` |
190+
| **Conversion to other** | `TaskSeq.toAsyncSeq` | [`AsyncSeq.toAsyncEnum`][22] |
191+
| **Conversion from other** | Implicit (`yield!`) or `TaskSeq.ofAsyncSeq` | [`AsyncSeq.ofAsyncEnum`][23] |
190192
| **Recursion in `yield!`** | **No** (requires F# support, upcoming) | Yes |
191-
| **Based on F# concept of** | `task` | `async` |
192-
| **`MoveNextAsync`** impl | `ValueTask<bool>` | `Async<'T option>` |
193-
| **Cancellation** | Implicit token governs iteration | Implicit token flows to all subtasks per `async` semantics |
194-
| **Performance** | Very high, negligible allocations | Slower, more allocations, due to using `async` |
193+
| **Iteration semantics** | [Two operations][6], 'Next' is a value task, 'Current' must be called separately| One operation, 'Next' is `Async`, returns `option` with 'Current' |
194+
| **`MoveNextAsync`** | [Returns `ValueTask<bool>`][4] | Returns `Async<'T option>` |
195+
| **[`Current`][5]** | [Returns `'T`][5] | n/a |
196+
| **Cancellation** | See [#133][], until 0.3.0: use `GetAsyncEnumerator(cancelToken)` | Implicit token flows to all subtasks per `async` semantics |
197+
| **Performance** | Very high, negligible allocations | Slower, more allocations, due to using `async` and cont style |
195198
| **Parallelism** | Possible with ChildTask; support will follow | Supported explicitly |
196199

200+
<sup>¹⁾ <a id="tsnote1"></a>_Both `AsyncSeq` and `TaskSeq` use a type called `IAsyncEnumerable<'T>`, but only `TaskSeq` uses the type from the BCL Generic Collections. `AsyncSeq` supports .NET Framework 4.6.x and NetStandard 2.0 as well, which do not have this type in the BCL._</sup>
201+
197202
## Status & planning
198203

199204
This project has stable features currently, but before we go full "version one", we'd like to complete the surface area. This section covers the status of that, with a full list of implemented functions below. Here's the shortlist:
@@ -207,7 +212,7 @@ This project has stable features currently, but before we go full "version one",
207212

208213
### Implementation progress
209214

210-
As of 9 November 2022: [Nuget package available][21]. In this phase, we will frequently update the package. Current:
215+
As of 9 November 2022: [Nuget package available][21]. In this phase, we will frequently update the package, see [release notes.txt](release-notes.txt). Current version:
211216

212217
[![Nuget](https://img.shields.io/nuget/vpre/FSharp.Control.TaskSeq)](https://www.nuget.org/packages/FSharp.Control.TaskSeq/)
213218

@@ -553,11 +558,11 @@ module TaskSeq =
553558

554559
[1]: https://github.com/fsprojects/FSharp.Control.TaskSeq/pull/25
555560
[2]: https://github.com/xunit/xunit/issues/2587
556-
[3]: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerable-1?view=net-7.0
557-
[4]: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerator-1.movenextasync?view=net-7.0
558-
[5]: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerator-1?view=net-7.0
559-
[6]: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerable-1.getasyncenumerator?view=net-7.0
560-
[7]: https://learn.microsoft.com/en-us/dotnet/api/system.iasyncdisposable?view=net-7.0
561+
[3]: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerable-1?view=net-6.0
562+
[4]: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerator-1.movenextasync?view=net-6.0
563+
[5]: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerator-1.current?view=net-6.0
564+
[6]: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerable-1.getasyncenumerator?view=net-6.0
565+
[7]: https://learn.microsoft.com/en-us/dotnet/api/system.iasyncdisposable?view=net-6.0
561566
[8]: https://stu.dev/iasyncenumerable-introduction/
562567
[9]: https://learn.microsoft.com/en-us/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8
563568
[10]: https://gist.github.com/akhansari/d88812b742aa6be1c35b4f46bd9f8532
@@ -572,6 +577,8 @@ module TaskSeq =
572577
[19]: https://fsharpforfunandprofit.com/series/computation-expressions/
573578
[20]: https://github.com/dotnet/fsharp/blob/d5312aae8aad650f0043f055bb14c3aa8117e12e/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerf/taskSeq.fs
574579
[21]: https://www.nuget.org/packages/FSharp.Control.TaskSeq#versions-body-tab
580+
[22]: https://fsprojects.github.io/FSharp.Control.AsyncSeq/reference/fsharp-control-asyncseq.html#toAsyncEnum
581+
[23]: https://fsprojects.github.io/FSharp.Control.AsyncSeq/reference/fsharp-control-asyncseq.html#fromAsyncEnum
575582

576583
[#2]: https://github.com/fsprojects/FSharp.Control.TaskSeq/pull/2
577584
[#11]: https://github.com/fsprojects/FSharp.Control.TaskSeq/pull/11
@@ -587,6 +594,7 @@ module TaskSeq =
587594
[#83]: https://github.com/fsprojects/FSharp.Control.TaskSeq/pull/83
588595
[#90]: https://github.com/fsprojects/FSharp.Control.TaskSeq/pull/90
589596
[#126]: https://github.com/fsprojects/FSharp.Control.TaskSeq/pull/126
597+
[#133]: https://github.com/fsprojects/FSharp.Control.TaskSeq/issues/133
590598

591599
[issues]: https://github.com/fsprojects/FSharp.Control.TaskSeq/issues
592600
[nuget]: https://www.nuget.org/packages/FSharp.Control.TaskSeq/

release-notes.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
Release notes:
33
0.4.x (unreleased)
4+
- adds `let!` and `do!` support for F#'s Async<'T>
45
- adds TaskSeq.takeWhile, takeWhileAsync, takeWhileInclusive, takeWhileInclusiveAsync, #126 (by @bartelink)
56
- adds AsyncSeq vs TaskSeq comparison chart, #131
67

0 commit comments

Comments
 (0)