Skip to content

Typos / tweaks #125

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Dec 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 2 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,8 @@ _NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/
# Rider / JetBrains IDEs
.idea/

# Web workbench (sass)
.sass-cache/
Expand Down
26 changes: 19 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Latest version [can be installed from Nuget][nuget].

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].

Since the introduction of `task` in F# the call for a native implementation of _task sequences_ has grown, in particular because proper iterating over an `IAsyncEnumerable` has proven challenging, especially if one wants to avoid mutable variables. This library is an answer to that call and implements the same _resumable state machine_ approach with `taskSeq`.
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`.

### Module functions

Expand All @@ -58,9 +58,12 @@ As with `seq` and `Seq`, this library comes with a bunch of well-known collectio

### `taskSeq` computation expressions

The `taskSeq` computation expression can be used just like using `seq`. On top of that, it adds support for working with tasks through `let!` and
looping over a normal or asynchronous sequence (one that implements `IAsyncEnumerable<'T>'`). You can use `yield!` and `yield` and there's support
for `use` and `use!`, `try-with` and `try-finally` and `while` loops within the task sequence expression:
The `taskSeq` computation expression can be used just like using `seq`.
Additionally, it adds support for working with `Task`s through `let!` and
looping over both normal and asynchronous sequences (ones that implement
`IAsyncEnumerable<'T>'`). You can use `yield!` and `yield` and there's support
for `use` and `use!`, `try-with` and `try-finally` and `while` loops within
the task sequence expression:

### Installation

Expand Down Expand Up @@ -183,7 +186,7 @@ The _resumable state machine_ backing the `taskSeq` CE is now finished and _rest

### Progress and implemented `TaskSeq` module functions

We are working hard on getting a full set of module functions on `TaskSeq` that can be used with `IAsyncEnumerable` sequences. Our guide is the set of F# `Seq` functions in F# Core and, where applicable, the functions provided from `AsyncSeq`. Each implemented function is documented through XML doc comments to provide the necessary context-sensitive help.
We are working hard on getting a full set of module functions on `TaskSeq` that can be used with `IAsyncEnumerable` sequences. Our guide is the set of F# `Seq` functions in F# Core and, where applicable, the functions provided by `AsyncSeq`. Each implemented function is documented through XML doc comments to provide the necessary context-sensitive help.

The following is the progress report:

Expand Down Expand Up @@ -327,12 +330,17 @@ The following is the progress report:

## More information

### Further reading `IAsyncEnumerable`
### 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].
- [An MSDN article][9] written shortly after it was introduced.
- Converting a `seq` to an `IAsyncEnumerable` [demo gist][10] as an example, though `TaskSeq` contains many more utility functions and uses a slightly different approach.
- If you're looking for using `IAsyncEnumerable` with `async` and not `task`, the excellent [`AsyncSeq`][11] library should be used. While `TaskSeq` is intended to consume `async` just like `task` does, it won't create an `AsyncSeq` type (at least not yet). If you want classic Async and parallelism, you should get this library instead.

### Further reading on resumable state machines

Expand Down Expand Up @@ -487,6 +495,10 @@ module TaskSeq =
val prependSeq: source1: #seq<'T> -> source2: #taskSeq<'T> -> taskSeq<'T>
val singleton: source: 'T -> taskSeq<'T>
val tail: source: taskSeq<'T> -> Task<taskSeq<'T>>
val takeWhile: predicate: ('T -> bool) -> source: taskSeq<'T> -> Task<taskSeq<'T>>
val takeWhileAsync: predicate: ('T -> #Task<bool>) -> source: taskSeq<'T> -> Task<taskSeq<'T>>
val takeWhileInclusive: predicate: ('T -> bool) -> source: taskSeq<'T> -> Task<taskSeq<'T>>
val takeWhileInclusiveAsync: predicate: ('T -> #Task<bool>) -> source: taskSeq<'T> -> Task<taskSeq<'T>>
val toArray: source: taskSeq<'T> -> 'T[]
val toArrayAsync: source: taskSeq<'T> -> Task<'T[]>
val toIListAsync: source: taskSeq<'T> -> Task<IList<'T>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>

<IsPackable>false</IsPackable>
<GenerateProgramFile>false</GenerateProgramFile>
</PropertyGroup>

<ItemGroup>
Expand All @@ -13,7 +10,6 @@

<ItemGroup>
<Compile Include="SmokeTests.fs" />
<Compile Include="Program.fs" />
</ItemGroup>

<ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion src/FSharp.Control.TaskSeq.SmokeTests/Program.fs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
<Compile Include="TaskSeq.Do.Tests.fs" />
<Compile Include="TaskSeq.Let.Tests.fs" />
<Compile Include="TaskSeq.Using.Tests.fs" />
<Compile Include="Program.fs" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/FSharp.Control.TaskSeq.Test/Nunit.Extensions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ module ExtraCustomMatchers =
/// Asserts any exception that matches, or is derived from the given exception <see cref="Type" />.
/// Async exceptions are almost always nested in an <see cref="AggregateException" />, however, in an
/// async try/catch in F#, the exception is typically unwrapped. But this is not foolproof, and
/// in cases where we just call <see cref="Task.Wait" />, and <see cref="AggregateException" /> will be raised regardless.
/// in cases where we just call <see cref="Task.Wait" />, an <see cref="AggregateException" /> will be raised regardless.
/// This assertion will go over all nested exceptions and 'self', to find a matching exception.
/// Function to evaluate MUST return a <see cref="System.Threading.Tasks.Task" />, not a generic
/// <see cref="Task&lt;'T>" />.
Expand Down
3 changes: 0 additions & 3 deletions src/FSharp.Control.TaskSeq.Test/Program.fs

This file was deleted.

4 changes: 2 additions & 2 deletions src/FSharp.Control.TaskSeq/FSharp.Control.TaskSeq.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
<Authors>Abel Braaksma; Don Syme</Authors>
<Description>This library brings C#'s concept of 'await foreach' to F#, with a seamless implementation of IAsyncEnumerable&lt;'T&gt;.

The 'taskSeq' computation expression adds support for awaitable asyncronous sequences with a similar ease of use and performance as F#'s 'task' CE, with minimal overhead through ValueTask under the hood. TaskSeq brings 'seq' and 'task' together in a safe way.
The 'taskSeq' computation expression adds support for awaitable asynchronous sequences with similar ease of use and performance to F#'s 'task' CE, with minimal overhead through ValueTask under the hood. TaskSeq brings 'seq' and 'task' together in a safe way.

Generates optimized IL code through the new resumable state machines, and comes with a comprehensive set of helpful functions in module 'TaskSeq'. See README for documentation and more info.</Description>
Generates optimized IL code through resumable state machines, and comes with a comprehensive set of functions in module 'TaskSeq'. See README for documentation and more info.</Description>
<Copyright>Copyright 2022</Copyright>
<PackageProjectUrl>https://github.com/fsprojects/FSharp.Control.TaskSeq</PackageProjectUrl>
<RepositoryUrl>https://github.com/fsprojects/FSharp.Control.TaskSeq</RepositoryUrl>
Expand Down