Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 31 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,16 @@ Latest version [can be installed from Nuget][nuget].
- [`taskSeq` computation expressions](#taskseq-computation-expressions)
- [Installation](#installation)
- [Examples](#examples)
- [Status & planning](#status--planning)
- [Choosing between `AsyncSeq` and `TaskSeq`](#choosing-between-asyncseq-and-taskseq)
- [Status \& planning](#status--planning)
- [Implementation progress](#implementation-progress)
- [Progress `taskSeq` CE](#progress-taskseq-ce)
- [Progress and implemented `TaskSeq` module functions](#progress-and-implemented-taskseq-module-functions)
- [More information](#more-information)
- [Further reading `IAsyncEnumerable`](#further-reading-iasyncenumerable)
- [Further reading on `IAsyncEnumerable`](#further-reading-on-iasyncenumerable)
- [Further reading on resumable state machines](#further-reading-on-resumable-state-machines)
- [Further reading on computation expressions](#further-reading-on-computation-expressions)
- [Building & testing](#building--testing)
- [Building \& testing](#building--testing)
- [Prerequisites](#prerequisites)
- [Build the solution](#build-the-solution)
- [Run the tests](#run-the-tests)
Expand Down Expand Up @@ -163,6 +164,33 @@ let feedFromTwitter user pwd = taskSeq {
}
```

## Choosing between `AsyncSeq` and `TaskSeq`

The [`AsyncSeq`][11] and `TaskSeq` library both operate on asynchronous sequences, but there are a few fundamental differences, most notably that the former _does not_ implement `IAsyncEnumerable<'T>`, but has its own same-named, but differently behaving type. Another core difference is that `TaskSeq` uses `ValueTasks` for the asynchronous computations, and `AsyncSeq` uses F#'s `Async<'T>`.
Comment thread
abelbraaksma marked this conversation as resolved.
Outdated

There are more differences:

| | `TaskSeq` | `AsyncSeq` |
|----------------------------|---------------------------------------------------------------------------------------|----------------------------------------------------------------------|
| **Frameworks** | .NET 5.0+, NetStandard 2.1 | .NET 5.0+, NetStandard 2.0 and 2.1, .NET Framework 4.6.1+ |
| **Underlying type** | `System.Collections.Generic.IAsyncEnumerable<'T>` | Its own type, also called `IAsyncEnumerable<'T>`, but not compatible |
Comment thread
abelbraaksma marked this conversation as resolved.
Outdated
| **Implementation** | State machine (statically compiled) | No state machine, continuation style |
| **Semantics** | `seq`-like: on-demand | `seq`-like: on-demand |
| **Support `let!`** | All `task`-like: `Async<'T>`, `ValueTask<'T>`, `Task<'T>` or any `GetAwaiter()` | `Async<'T>` only |
Comment thread
abelbraaksma marked this conversation as resolved.
Outdated
| **Support `do!`** | `Async<unit>`, `Task<unit>` and `Task`, `ValueTask<unit>` and `ValueTask` | `Async<unit>` only |
Comment thread
abelbraaksma marked this conversation as resolved.
Outdated
| **Support `yield!`** | `IAsyncEnumerable<'T>`, `AsyncSeq`, any sequence | `AsyncSeq` |
| **Support `for`** | `IAsyncEnumerable<'T>`, `AsyncSeq`, any sequence | `AsyncSeq` any sequence |
Comment thread
abelbraaksma marked this conversation as resolved.
Outdated
| **Behavior with `yield`** | Zero allocations, no `Task` or even `ValueTask` created | Allocated, an F# `Async` wrapped in a singleton `AsyncSeq` |
Comment thread
abelbraaksma marked this conversation as resolved.
Outdated
| **Conversion to other** | `TaskSeq.toAsyncSeq` | `AsyncSeq.toAsyncEnum` |
| **Conversion from other** | Implicit (yield!) or `TaskSeq.ofAsyncSeq` | `AsyncSeq.ofAsyncEnum` |
Comment thread
abelbraaksma marked this conversation as resolved.
Outdated
| **Recursion in `yield!`** | No (requires F# support, upcoming) | Yes |
Comment thread
abelbraaksma marked this conversation as resolved.
Outdated
| **Based on F# concept of** | `task` | `async` |
Comment thread
abelbraaksma marked this conversation as resolved.
Outdated
| **`MoveNextAsync`** | `ValueTask<bool>` | `Async<'T option>` |
| **`Current` internals** | `ValueOption<'T>` | `Option<'T>` |
Comment thread
abelbraaksma marked this conversation as resolved.
Outdated
| **Cancellation** | Implicit token governing iteration | Implicit token passed to each subtask |
Comment thread
abelbraaksma marked this conversation as resolved.
Outdated
| **Performance** | Very high, negligible allocations | Slower, more allocations, due to using `async` |
| **Parallelism** | Possible with ChildTask, support will follow | Supported explicitly |
Comment thread
abelbraaksma marked this conversation as resolved.
Outdated

## Status & planning

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 implmented functions below. Here's the short list:
Comment thread
abelbraaksma marked this conversation as resolved.
Outdated
Expand Down Expand Up @@ -330,12 +358,6 @@ The following is the progress report:

## More information

### The AsyncSeq library

If you're looking to use `IAsyncEnumerable` with `async` and not `task`, the existing [`AsyncSeq`][11] library already provides excellent coverage of that use case. While `TaskSeq` is intended to interoperate with `async` as `task` does, it's not intended to provide an `AsyncSeq` type (at least not yet).

In short, if your application is using `Async` (and the parallelism features stemming from that), consider using the `AsyncSeq` library instead.

### Further reading on `IAsyncEnumerable`

- A good C#-based introduction [can be found in this blog][8].
Expand Down