aboutsummaryrefslogtreecommitdiff
path: root/carboxyl/index.html
blob: 345e4c3f3024da48513eaa926864ba99d4fdfa64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="generator" content="rustdoc">
    <meta name="description" content="API documentation for the Rust `carboxyl` crate.">
    <meta name="keywords" content="rust, rustlang, rust-lang, carboxyl">

    <title>carboxyl - Rust</title>

    <link rel="stylesheet" type="text/css" href="../main.css">

    
    
</head>
<body class="rustdoc">
    <!--[if lte IE 8]>
    <div class="warning">
        This old browser is unsupported and will most likely display funky
        things.
    </div>
    <![endif]-->

    

    <section class="sidebar">
        
        <p class='location'></p><script>window.sidebarCurrent = {name: 'carboxyl', ty: 'mod', relpath: '../'};</script>
    </section>

    <nav class="sub">
        <form class="search-form js-only">
            <div class="search-container">
                <input class="search-input" name="search"
                       autocomplete="off"
                       placeholder="Click or press 'S' to search, '?' for more options..."
                       type="search">
            </div>
        </form>
    </nav>

    <section id='main' class="content mod">
<h1 class='fqn'><span class='in-band'>Crate <a class='mod' href=''>carboxyl</a></span><span class='out-of-band'><span id='render-detail'>
            <a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs">
                [<span class='inner'>&#x2212;</span>]
            </a>
        </span><a id='src-0' class='srclink' href='../src/carboxyl/lib.rs.html#1-161' title='goto source code'>[src]</a></span></h1>
<div class='docblock'><p><em>Carboxyl</em> provides primitives for functional reactive programming in Rust.
It draws inspiration from the <a href="https://github.com/SodiumFRP/sodium/">Sodium</a> libraries and Push-Pull FRP,
as described by <a href="http://conal.net/papers/push-pull-frp/push-pull-frp.pdf">Elliott (2009)</a>.</p>

<h1 id="overview" class='section-header'><a
                           href="#overview">Overview</a></h1>
<p>Functional reactive programming (FRP) is a composable and modular
abstraction for creating dynamic and reactive systems. In its most general
form it models these systems as a composition of two basic primitives:
<em>streams</em> are a series of singular events and <em>signals</em> are continuously
changing values.</p>

<p><em>Carboxyl</em> is an imperative, hybrid push- and pull-based implementation of
FRP. Streams and the discrete components of signals are data-driven, i.e.
whenever an event occurs the resulting changes are propagated to everything
that depends on it.</p>

<p>However, the continuous components of signals are demand-driven. Internally,
<em>Carboxyl</em> stores the state of a signal as a function. This function has to
be evaluated by consumers of a signal to obtain a concrete value.</p>

<p>Nonetheless, <em>Carboxyl</em> has no explicit notion of time. Its signals are
functions that can be evaluated at any time, but they do not carry any
inherent notion of time. Synchronization and atomicity is achieved by a
transaction system.</p>

<h1 id="functional-reactive-primitives" class='section-header'><a
                           href="#functional-reactive-primitives">Functional reactive primitives</a></h1>
<p>This library provides two basic types: <code>Stream</code> and <code>Signal</code>. A stream is a
discrete sequence of events, a signal is a container for values that change
(discretely) over time.</p>

<p>The FRP primitives are mostly implemented as methods of the basic types to
ease method chaining, except for the various lifting functions, as they do
not really belong to any type in particular.</p>

<p>In addition, the <code>Sink</code> type allows one to create a stream of events by
sending values into it. It is the only way to create a stream from scratch,
i.e. without using any of the other primitives.</p>

<h1 id="usage-example" class='section-header'><a
                           href="#usage-example">Usage example</a></h1>
<p>Here is a simple example of how you can use the primitives provided by
<em>Carboxyl</em>. First of all, events can be sent into a <em>sink</em>. From a sink one
can create a <em>stream</em> of events. Streams can also be filtered, mapped and
merged. One can e.g. hold the last event from a stream as a signal.</p>
<pre class='rust rust-example-rendered'>
<span class='kw'>use</span> <span class='ident'>carboxyl</span>::<span class='ident'>Sink</span>;

<span class='kw'>let</span> <span class='ident'>sink</span> <span class='op'>=</span> <span class='ident'>Sink</span>::<span class='ident'>new</span>();
<span class='kw'>let</span> <span class='ident'>stream</span> <span class='op'>=</span> <span class='ident'>sink</span>.<span class='ident'>stream</span>();
<span class='kw'>let</span> <span class='ident'>signal</span> <span class='op'>=</span> <span class='ident'>stream</span>.<span class='ident'>hold</span>(<span class='number'>3</span>);

<span class='comment'>// The current value of the signal is initially 3</span>
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>signal</span>.<span class='ident'>sample</span>(), <span class='number'>3</span>);

<span class='comment'>// When we fire an event, the signal get updated accordingly</span>
<span class='ident'>sink</span>.<span class='ident'>send</span>(<span class='number'>5</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>signal</span>.<span class='ident'>sample</span>(), <span class='number'>5</span>);
</pre>

<p>One can also directly iterate over the stream instead of holding it in a
signal:</p>
<pre class='rust rust-example-rendered'>
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>events</span> <span class='op'>=</span> <span class='ident'>stream</span>.<span class='ident'>events</span>();
<span class='ident'>sink</span>.<span class='ident'>send</span>(<span class='number'>4</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>events</span>.<span class='ident'>next</span>(), <span class='prelude-val'>Some</span>(<span class='number'>4</span>));
</pre>

<p>Streams and signals can be combined using various primitives. We can map a
stream to another stream using a function:</p>
<pre class='rust rust-example-rendered'>
<span class='kw'>let</span> <span class='ident'>squares</span> <span class='op'>=</span> <span class='ident'>stream</span>.<span class='ident'>map</span>(<span class='op'>|</span><span class='ident'>x</span><span class='op'>|</span> <span class='ident'>x</span> <span class='op'>*</span> <span class='ident'>x</span>).<span class='ident'>hold</span>(<span class='number'>0</span>);
<span class='ident'>sink</span>.<span class='ident'>send</span>(<span class='number'>4</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>squares</span>.<span class='ident'>sample</span>(), <span class='number'>16</span>);
</pre>

<p>Or we can filter a stream to create a new one that only contains events that
satisfy a certain predicate:</p>
<pre class='rust rust-example-rendered'>
<span class='kw'>let</span> <span class='ident'>negatives</span> <span class='op'>=</span> <span class='ident'>stream</span>.<span class='ident'>filter</span>(<span class='op'>|</span><span class='kw-2'>&amp;</span><span class='ident'>x</span><span class='op'>|</span> <span class='ident'>x</span> <span class='op'>&lt;</span> <span class='number'>0</span>).<span class='ident'>hold</span>(<span class='number'>0</span>);

<span class='comment'>// This won&#39;t arrive at the signal.</span>
<span class='ident'>sink</span>.<span class='ident'>send</span>(<span class='number'>4</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>negatives</span>.<span class='ident'>sample</span>(), <span class='number'>0</span>);

<span class='comment'>// But this will!</span>
<span class='ident'>sink</span>.<span class='ident'>send</span>(<span class='op'>-</span><span class='number'>3</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>negatives</span>.<span class='ident'>sample</span>(), <span class='op'>-</span><span class='number'>3</span>);
</pre>

<p>There are some other methods on streams and signals, that you can find in
their respective APIs.</p>

<p>Note that all these objects are <code>Send + Sync + Clone</code>. This means you can
easily pass them around in your code, make clones, give them to another
thread, and they will still be updated correctly.</p>

<p>You may have noticed that certain primitives take a function as an argument.
There is a limitation on what kind of functions can and should be used here.
In general, as FRP provides an abstraction around mutable state, they should
be pure functions (i.e. free of side effects).</p>

<p>For the most part this is guaranteed by Rust&#39;s type system. A static
function with a matching signature always works. A closure though is very
restricted: it must not borrow its environment, as it is impossible to
satisfy the lifetime requirements for that. So you can only move stuff into
it from the environment. However, the moved contents of the closure may also
not be altered, which is guaranteed by the <code>Fn(…) -&gt; …)</code> trait bound.</p>

<p>However, both closures and functions could still have side effects such as
I/O, changing mutable state via <code>Mutex</code> or <code>RefCell</code>, etc. While Rust&#39;s type
system cannot prevent this, you should generally not pass such functions to
the FRP primitives, as they break the benefits you get from using FRP.
(An exception here is debugging output.)</p>
</div><h2 id='modules' class='section-header'><a href="#modules">Modules</a></h2>
<table>
                    <tr class=' module-item'>
                        <td><a class='mod' href='lift/index.html'
                               title='carboxyl::lift'>lift</a></td>
                        <td class='docblock short'>
                             <p>Lifting of n-ary functions.</p>

                        </td>
                    </tr>
                </table><h2 id='macros' class='section-header'><a href="#macros">Macros</a></h2>
<table>
                    <tr class=' module-item'>
                        <td><a class='macro' href='macro.lift!.html'
                               title='carboxyl::lift!'>lift!</a></td>
                        <td class='docblock short'>
                             
                        </td>
                    </tr>
                </table><h2 id='structs' class='section-header'><a href="#structs">Structs</a></h2>
<table>
                    <tr class=' module-item'>
                        <td><a class='struct' href='struct.Signal.html'
                               title='carboxyl::Signal'>Signal</a></td>
                        <td class='docblock short'>
                             <p>A continuous signal that changes over time.</p>

                        </td>
                    </tr>
                
                    <tr class=' module-item'>
                        <td><a class='struct' href='struct.SignalMut.html'
                               title='carboxyl::SignalMut'>SignalMut</a></td>
                        <td class='docblock short'>
                             <p>Signal variant using inner mutability for efficient in-place updates.</p>

                        </td>
                    </tr>
                
                    <tr class=' module-item'>
                        <td><a class='struct' href='struct.Sink.html'
                               title='carboxyl::Sink'>Sink</a></td>
                        <td class='docblock short'>
                             <p>An event sink.</p>

                        </td>
                    </tr>
                
                    <tr class=' module-item'>
                        <td><a class='struct' href='struct.Stream.html'
                               title='carboxyl::Stream'>Stream</a></td>
                        <td class='docblock short'>
                             <p>A stream of events.</p>

                        </td>
                    </tr>
                </table></section>
    <section id='search' class="content hidden"></section>

    <section class="footer"></section>

    <div id="help" class="hidden">
        <div class="shortcuts">
            <h1>Keyboard shortcuts</h1>
            <dl>
                <dt>?</dt>
                <dd>Show this help dialog</dd>
                <dt>S</dt>
                <dd>Focus the search field</dd>
                <dt>&larrb;</dt>
                <dd>Move up in search results</dd>
                <dt>&rarrb;</dt>
                <dd>Move down in search results</dd>
                <dt>&#9166;</dt>
                <dd>Go to active search result</dd>
            </dl>
        </div>
        <div class="infos">
            <h1>Search tricks</h1>
            <p>
                Prefix searches with a type followed by a colon (e.g.
                <code>fn:</code>) to restrict the search to a given type.
            </p>
            <p>
                Accepted types are: <code>fn</code>, <code>mod</code>,
                <code>struct</code>, <code>enum</code>,
                <code>trait</code>, <code>typedef</code> (or
                <code>tdef</code>).
            </p>
            <p>
                Search functions by type signature (e.g.
                <code>vec -> usize</code>)
            </p>
        </div>
    </div>

    

    <script>
        window.rootPath = "../";
        window.currentCrate = "carboxyl";
        window.playgroundUrl = "";
    </script>
    <script src="../jquery.js"></script>
    <script src="../main.js"></script>
    
    <script async src="../search-index.js"></script>
</body>
</html>