Skip to content
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
4 changes: 3 additions & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
### 1.12.2 - 27.03.2015
### 1.13 - 27.03.2015
* Renamed to FSharp.Control.AsyncSeq
* Remove surface area
* Hide Nil/Cons from representation of AsyncSeq

### 1.12.1 - 27.03.2015
* Added Async.bindChoice, Async.ParallelIgnore, AsyncSeq.zipWithAsync, AsyncSeq.zappAsync, AsyncSeq.threadStateAsync, AsyncSeq.merge, AsyncSeq.traverseOptionAsync, AsyncSeq.traverseChoiceAsync
Expand Down
2 changes: 1 addition & 1 deletion docs/content/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ This includes additional brief samples on using most of the functions.

[Terminology](terminology.html) a reference for some of the terminology around F# async.

[FSharp.Control.AsyncSeq](library/fsharp-control-AsyncSeq.html) contains narrative and code samples explaining asynchronous sequences.
[FSharp.Control.AsyncSeq](library/AsyncSeq.html) contains narrative and code samples explaining asynchronous sequences.

Contributing and copyright
--------------------------
Expand Down
19 changes: 10 additions & 9 deletions docs/content/library/AsyncSeq.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
# F# Async: FSharp.Control.AsyncSeq

An AsyncSeq is a sequence in which individual elements are retrieved using an `Async` computation.
It is similar to `seq<'a>` in that subsequent elements are pulled lazily. Structurally it is
It is similar to `seq<'a>` in that subsequent elements are pulled on-demand. Structurally it is
similar to `list<'a>` with the difference being that each head and tail node or empty node is wrapped
in `Async`. `AsyncSeq` also bears similarity to `IObservable<'a>` with the former being pull-based and the
latter push-based. Analogs for most operations defined for `Seq`, `List` and `IObservable` are also defined for
in `Async`. `AsyncSeq` also bears similarity to `IObservable<'a>` with the former being based on an "asynchronous pull" and the
latter based on a "synchronous push". Analogs for most operations defined for `Seq`, `List` and `IObservable` are also defined for
`AsyncSeq`. The power of `AsyncSeq` lies in that many of these operations also have analogs based on `Async`
allowing composition of complex asynchronous workflows.

Expand Down Expand Up @@ -144,9 +144,10 @@ in a blocking manner.
### Comparison with IObservable<'a>

Both `IObservable<'a>` and `AsyncSeq<'a>` represent collections of items and both provide similar operations
for transformation and composition. The central difference between the two is that the former is push-based
and the latter is pull-based. Consumers of an `IObservable<'a>` *subscribe* to receive notifications about
new items or the end of the sequence. By contrast, consumers of an `AsyncSeq<'a>` *retrieve* subsequent items on their own
for transformation and composition. The central difference between the two is that the former uses a *synchronous push*
to a subscriber and the latter uses an *asynchronous pull* by a consumer.
Consumers of an `IObservable<'a>` *subscribe* to receive notifications about
new items or the end of the sequence. By contrast, consumers of an `AsyncSeq<'a>` *asynchronously retrieve* subsequent items on their own
terms. Some domains are more naturally modeled with one or the other, however it is less clear which is a more
suitable tool for a specific task. In many cases, a combination of the two provides the optimal solution and
restricting yourself to one, while simplifying the programming model, can lead one to view all problems as a nail.
Expand Down Expand Up @@ -237,15 +238,15 @@ let storedTeetsObs' : IObservable<unit> =

(**
Overall, both solutions are succinct and composable and deciding which one to use can ultimately be a matter of preference.
Some things to consider are the push vs. pull semantics. On the one hand, tweets are pushed based - the consumer has no control
Some things to consider are the "synchronous push" vs. "asynchronous pull" semantics. On the one hand, tweets are pushed based - the consumer has no control
over their generation. On the other hand, the program at hand will process the tweets on its own terms regardless of how quickly
they are being generated. Moreover, the underlying Twitter API will likely utilize a request-reply protocol to retrieve batches of
tweets from persistent storage. As such, the distinction between push vs. pull becomes less interesting. If the underlying source
tweets from persistent storage. As such, the distinction between "synchronous push" vs. "asynchronous pull" becomes less interesting. If the underlying source
is truly push-based, then one can buffer its output and consume it using an asynchronous sequence. If the underlying source is pull-based,
then one can turn it into an observable sequence by first pulling, then pushing. Note however that in a true real-time reactive system,
notifications must be pushed immediately without delay.

Upon closer inspection, the consumption approaches between the two models aren't all too different. While `AsyncSeq` is pull based,
Upon closer inspection, the consumption approaches between the two models aren't all too different. While `AsyncSeq` is based on an asynchronous-pull operation,
it is usually consumed using an operator such as `AsyncSeq.iterAsync` as shown above. This is a function of type
`('a -> Async<unit>) -> AsyncSeq<'a> -> Async<unit>` where the first argument is a function `'a -> Async<unit>` which performs
some work on an item of the sequence and is applied repeatedly to subsequent items. In a sense, `iterAsync` *pushes* values to this
Expand Down
2 changes: 1 addition & 1 deletion docs/tools/templates/template.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
<li class="divider"></li>
<li class="nav-header">Documentation</li>
<li><a href="@Root/terminology.html">Terminology</a></li>
<li><a href="@Root/library/fsharp-control-AsyncSeq.html">AsyncSeq</a></li>
<li><a href="@Root/library/AsyncSeq.html">AsyncSeq</a></li>
<li><a href="@Root/reference/index.html">API Reference</a></li>
</ul>
</div>
Expand Down
6 changes: 3 additions & 3 deletions src/FSharp.Control.AsyncSeq/AssemblyInfo.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("FSharp.Control.AsyncSeq")>]
[<assembly: AssemblyProductAttribute("FSharp.Control.AsyncSeq")>]
[<assembly: AssemblyDescriptionAttribute("Asynchronous sequences for F#")>]
[<assembly: AssemblyVersionAttribute("1.12.2")>]
[<assembly: AssemblyFileVersionAttribute("1.12.2")>]
[<assembly: AssemblyVersionAttribute("1.13")>]
[<assembly: AssemblyFileVersionAttribute("1.13")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] Version = "1.12.2"
let [<Literal>] Version = "1.13"
3 changes: 2 additions & 1 deletion src/FSharp.Control.AsyncSeq/AsyncSeq.fs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ type AsyncSeq<'T> = Async<AsyncSeqInner<'T>>

/// The interanl type that represents a value returned as a result of
/// evaluating a step of an asynchronous sequence
and AsyncSeqInner<'T> =
and AsyncSeqInner<'T> =
internal
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow. I think that's the first time I see it in that position.

| Nil
| Cons of 'T * AsyncSeq<'T>

Expand Down