Skip to content

Commit d93df47

Browse files
committed
deploy: 41a9741
0 parents  commit d93df47

48 files changed

Lines changed: 29119 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.nojekyll

Whitespace-only changes.

AsyncSeq.fsx

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
(**
2+
3+
*)
4+
#r "nuget: FSharp.Control.AsyncSeq,4.7.0"
5+
(**
6+
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/fsprojects/FSharp.Control.AsyncSeq/gh-pages?filepath=AsyncSeq.ipynb)
7+
8+
# F# Asynchronous Sequences
9+
10+
An asynchronous sequence is a sequence in which individual elements are **awaited**, so the next element of the sequence is not necessarily available immediately. This allows for efficient composition of asynchronous workflows which involve sequences of data.
11+
12+
FSharp.Control.AsyncSeq is an implementation of functional-first programming over asynchronous sequences for F#. The central type of the library, `AsyncSeq<'T>`, is a type alias for the standard type `System.Collections.Generic.IAsyncEnumerable<'T>`.
13+
14+
This library was also [one of the world's first implementations of langauge integrated asynchronous sequences](http://tomasp.net/blog/async-sequences.aspx) - that is, asynchronous sequences with integrated language support through computation expressions. It is a mature library used in production for many years and is widely used in the F# community.
15+
16+
### Generating asynchronous sequences
17+
18+
To use the library, referrence the NuGet package `FSharp.Control.AsyncSeq` in your project and open the `FSharp.Control` namespace:
19+
20+
*)
21+
open FSharp.Control
22+
(**
23+
An asynchronous sequence can be generated using a computation expression:
24+
25+
*)
26+
let async12 = asyncSeq {
27+
yield 1
28+
yield 2
29+
}
30+
(**
31+
or more succinctly:
32+
33+
*)
34+
let async12b = asyncSeq { 1; 2 }
35+
(**
36+
### Comparison with `FSharp.Control.TaskSeq`
37+
38+
A related library is [`FSharp.Control.TaskSeq`](https://github.com/fsprojects/FSharp.Control.TaskSeq/) which provides a similar API for sequences of `Task<'T>` instead of `Async<'T>`. The two libraries are very similar and the choice between them is mostly a matter of preference or performance. The `AsyncSeq` library integrates well with the F# `Async` type, while the `TaskSeq` library is more performant and integrates well with the .NET `Task` type.
39+
40+
Both libraries implement that .NET standard `IAsyncEnumerable<'T>` interface, so they can be used interchangeably in most scenarios.
41+
42+
### Comparison with seq<'T>
43+
44+
The central difference between `seq<'T>` and `AsyncSeq<'T>` can be illustrated by introducing the notion of time.
45+
Suppose that generating subsequent elements of a sequence requires an IO-bound operation. Invoking long
46+
running IO-bound operations from within a `seq<'T>` will **block** the thread which calls `MoveNext` on the
47+
corresponding `IEnumerator`. An `AsyncSeq` on the other hand can use facilities provided by the F# `Async` type to make
48+
more efficient use of system resources.
49+
50+
*)
51+
open System.Threading
52+
53+
let withTime = seq {
54+
Thread.Sleep(1000) // calling thread will block
55+
yield 1
56+
Thread.Sleep(1000) // calling thread will block
57+
yield 1
58+
}
59+
60+
let withTime2 = asyncSeq {
61+
do! Async.Sleep 1000 // non-blocking sleep
62+
yield 1
63+
do! Async.Sleep 1000 // non-blocking sleep
64+
yield 2
65+
}
66+
(**
67+
When the asynchronous sequence `withTime'` is iterated, the calls to `Async.Sleep` won't block threads. Instead,
68+
the **continuation** of the sequence will be scheduled by `Async` while the calling thread will be free to perform other work.
69+
Overall, a `seq<'a>` can be viewed as a special case of an `AsyncSeq<'a>` where subsequent elements are retrieved
70+
in a blocking manner.
71+
72+
### Performance Considerations
73+
74+
While an asynchronous computation obviates the need to block an OS thread for the duration of an operation, it isn't always the case
75+
that this will improve the overall performance of an application. Note however that an async computation does not **require** a
76+
non-blocking operation, it simply allows for it. Also of note is that unlike calling `IEnumerable.MoveNext()`, consuming
77+
an item from an asynchronous sequence requires several allocations. Usually this is greatly outweighed by the
78+
benefits, it can make a difference in some scenarios.
79+
80+
## Related Articles
81+
82+
* [Programming with F# asynchronous sequences](http://tomasp.net/blog/async-sequences.aspx/)
83+
84+
*)
85+

AsyncSeq.html

Lines changed: 318 additions & 0 deletions
Large diffs are not rendered by default.

AsyncSeq.ipynb

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
2+
{
3+
"cells": [
4+
{
5+
"cell_type": "markdown",
6+
"metadata": {},
7+
8+
"source": [
9+
10+
]
11+
}
12+
,
13+
{
14+
"cell_type": "code",
15+
"metadata": {
16+
"dotnet_interactive": {
17+
"language": "fsharp"
18+
},
19+
"polyglot_notebook": {
20+
"kernelName": "fsharp"
21+
}
22+
},
23+
"execution_count": null, "outputs": [],
24+
"source": [
25+
"#r \"nuget: FSharp.Control.AsyncSeq,4.7.0\"\n"
26+
]
27+
}
28+
,
29+
{
30+
"cell_type": "markdown",
31+
"metadata": {},
32+
33+
"source": [
34+
"[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/fsprojects/FSharp.Control.AsyncSeq/gh-pages?filepath=AsyncSeq.ipynb)\n",
35+
"\n",
36+
"# F# Asynchronous Sequences\n",
37+
"\n",
38+
"An asynchronous sequence is a sequence in which individual elements are **awaited**, so the next element of the sequence is not necessarily available immediately. This allows for efficient composition of asynchronous workflows which involve sequences of data.\n",
39+
"\n",
40+
"FSharp.Control.AsyncSeq is an implementation of functional-first programming over asynchronous sequences for F#. The central type of the library, `AsyncSeq\u003c\u0027T\u003e`, is a type alias for the standard type `System.Collections.Generic.IAsyncEnumerable\u003c\u0027T\u003e`.\n",
41+
"\n",
42+
"This library was also [one of the world\u0027s first implementations of langauge integrated asynchronous sequences](http://tomasp.net/blog/async-sequences.aspx) - that is, asynchronous sequences with integrated language support through computation expressions. It is a mature library used in production for many years and is widely used in the F# community.\n",
43+
"\n",
44+
"### Generating asynchronous sequences\n",
45+
"\n",
46+
"To use the library, referrence the NuGet package `FSharp.Control.AsyncSeq` in your project and open the `FSharp.Control` namespace:\n",
47+
"\n"
48+
]
49+
}
50+
,
51+
{
52+
"cell_type": "code",
53+
"metadata": {
54+
"dotnet_interactive": {
55+
"language": "fsharp"
56+
},
57+
"polyglot_notebook": {
58+
"kernelName": "fsharp"
59+
}
60+
},
61+
"execution_count": null, "outputs": [],
62+
"source": [
63+
"open FSharp.Control\n"
64+
]
65+
}
66+
,
67+
{
68+
"cell_type": "markdown",
69+
"metadata": {},
70+
71+
"source": [
72+
"An asynchronous sequence can be generated using a computation expression:\n",
73+
"\n"
74+
]
75+
}
76+
,
77+
{
78+
"cell_type": "code",
79+
"metadata": {
80+
"dotnet_interactive": {
81+
"language": "fsharp"
82+
},
83+
"polyglot_notebook": {
84+
"kernelName": "fsharp"
85+
}
86+
},
87+
"execution_count": null, "outputs": [],
88+
"source": [
89+
"let async12 = asyncSeq {\n",
90+
" yield 1\n",
91+
" yield 2\n",
92+
"}\n"
93+
]
94+
}
95+
,
96+
{
97+
"cell_type": "markdown",
98+
"metadata": {},
99+
100+
"source": [
101+
"or more succinctly:\n",
102+
"\n"
103+
]
104+
}
105+
,
106+
{
107+
"cell_type": "code",
108+
"metadata": {
109+
"dotnet_interactive": {
110+
"language": "fsharp"
111+
},
112+
"polyglot_notebook": {
113+
"kernelName": "fsharp"
114+
}
115+
},
116+
"execution_count": null, "outputs": [],
117+
"source": [
118+
"let async12b = asyncSeq { 1; 2 }\n"
119+
]
120+
}
121+
,
122+
{
123+
"cell_type": "markdown",
124+
"metadata": {},
125+
126+
"source": [
127+
"### Comparison with `FSharp.Control.TaskSeq`\n",
128+
"\n",
129+
"A related library is [`FSharp.Control.TaskSeq`](https://github.com/fsprojects/FSharp.Control.TaskSeq/) which provides a similar API for sequences of `Task\u003c\u0027T\u003e` instead of `Async\u003c\u0027T\u003e`. The two libraries are very similar and the choice between them is mostly a matter of preference or performance. The `AsyncSeq` library integrates well with the F# `Async` type, while the `TaskSeq` library is more performant and integrates well with the .NET `Task` type.\n",
130+
"\n",
131+
"Both libraries implement that .NET standard `IAsyncEnumerable\u003c\u0027T\u003e` interface, so they can be used interchangeably in most scenarios.\n",
132+
"\n",
133+
"### Comparison with seq\u003c\u0027T\u003e\n",
134+
"\n",
135+
"The central difference between `seq\u003c\u0027T\u003e` and `AsyncSeq\u003c\u0027T\u003e` can be illustrated by introducing the notion of time.\n",
136+
"Suppose that generating subsequent elements of a sequence requires an IO-bound operation. Invoking long\n",
137+
"running IO-bound operations from within a `seq\u003c\u0027T\u003e` will **block** the thread which calls `MoveNext` on the\n",
138+
"corresponding `IEnumerator`. An `AsyncSeq` on the other hand can use facilities provided by the F# `Async` type to make\n",
139+
"more efficient use of system resources.\n",
140+
"\n"
141+
]
142+
}
143+
,
144+
{
145+
"cell_type": "code",
146+
"metadata": {
147+
"dotnet_interactive": {
148+
"language": "fsharp"
149+
},
150+
"polyglot_notebook": {
151+
"kernelName": "fsharp"
152+
}
153+
},
154+
"execution_count": null, "outputs": [],
155+
"source": [
156+
"open System.Threading\n",
157+
"\n",
158+
"let withTime = seq {\n",
159+
" Thread.Sleep(1000) // calling thread will block\n",
160+
" yield 1\n",
161+
" Thread.Sleep(1000) // calling thread will block\n",
162+
" yield 1\n",
163+
"}\n",
164+
"\n",
165+
"let withTime2 = asyncSeq {\n",
166+
" do! Async.Sleep 1000 // non-blocking sleep\n",
167+
" yield 1\n",
168+
" do! Async.Sleep 1000 // non-blocking sleep\n",
169+
" yield 2\n",
170+
"}\n"
171+
]
172+
}
173+
,
174+
{
175+
"cell_type": "markdown",
176+
"metadata": {},
177+
178+
"source": [
179+
"When the asynchronous sequence `withTime\u0027` is iterated, the calls to `Async.Sleep` won\u0027t block threads. Instead,\n",
180+
"the **continuation** of the sequence will be scheduled by `Async` while the calling thread will be free to perform other work.\n",
181+
"Overall, a `seq\u003c\u0027a\u003e` can be viewed as a special case of an `AsyncSeq\u003c\u0027a\u003e` where subsequent elements are retrieved\n",
182+
"in a blocking manner.\n",
183+
"\n",
184+
"### Performance Considerations\n",
185+
"\n",
186+
"While an asynchronous computation obviates the need to block an OS thread for the duration of an operation, it isn\u0027t always the case\n",
187+
"that this will improve the overall performance of an application. Note however that an async computation does not **require** a\n",
188+
"non-blocking operation, it simply allows for it. Also of note is that unlike calling `IEnumerable.MoveNext()`, consuming\n",
189+
"an item from an asynchronous sequence requires several allocations. Usually this is greatly outweighed by the\n",
190+
"benefits, it can make a difference in some scenarios.\n",
191+
"\n",
192+
"## Related Articles\n",
193+
"\n",
194+
"* [Programming with F# asynchronous sequences](http://tomasp.net/blog/async-sequences.aspx/)\n",
195+
"\n"
196+
]
197+
}
198+
],
199+
"metadata": {
200+
"kernelspec": {
201+
"display_name": ".NET (F#)",
202+
"language": "F#",
203+
"name": ".net-fsharp"
204+
},
205+
"language_info": {
206+
"file_extension": ".fs",
207+
"mimetype": "text/x-fsharp",
208+
"name": "polyglot-notebook",
209+
"pygments_lexer": "fsharp"
210+
},
211+
"polyglot_notebook": {
212+
"kernelInfo": {
213+
"defaultKernelName": "fsharp",
214+
"items": [
215+
{
216+
"aliases": [],
217+
"languageName": "fsharp",
218+
"name": "fsharp"
219+
}
220+
]
221+
}
222+
}
223+
},
224+
"nbformat": 4,
225+
"nbformat_minor": 2
226+
}
227+

0 commit comments

Comments
 (0)