You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: reactivity.md
+49-39Lines changed: 49 additions & 39 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,9 +16,9 @@
16
16
17
17
# Concept
18
18
19
-
In version 0.6.0, Red introduced support for "reactive programming" to help reduce the size and complexity of Red programs. Red's reactive model relies on dataflow and object events, constructing a directed graph, and propagating changes in objects, all using a "push" model. More specifically, Red implements the [object-oriented reactive programming](https://en.wikipedia.org/wiki/Reactive_programming#Object-oriented) model, where only object fields can be the source of change.
19
+
In version 0.6.0, Red introduced support for "reactive programming" to help reduce the size and complexity of Red programs. Red's reactive model relies on dataflow and object events, constructing a directed graph, and propagating changes in objects. It uses a "push" model. More specifically, Red implements the [object-oriented reactive programming](https://en.wikipedia.org/wiki/Reactive_programming#Object-oriented) model, where only object fields can be the source of change.
20
20
21
-
If the description seems a bit abstract, don't worry, the reactive API and its use are simple and practical. Here are some graphs to help visualize reactive relationships.
21
+
The reactive API and its use are simple and practical, even if the description is abstract. Here are some diagrams to help visualize reactive relationships.
@@ -28,28 +28,27 @@ If the description seems a bit abstract, don't worry, the reactive API and its u
28
28
29
29
*Graphs C, D & E show chained reactions, where some targets are, themselves, reactors, setting up a chain of relations that can have any shape.*
30
30
31
-
32
31
Reactions are run asynchronously, when a source field(s) value is changed. The reaction relationship is maintained until the reaction is explicitly destroyed using `react/unlink` or `clear-reactions`.
33
32
34
33
Only the source objects in a reactive expression need to be a reactor. The target can be a simple object. If the target is also a reactor, reactions are chained and a graph of relations is constructed implicitly.
35
34
36
35
Notes:
37
-
* Red's reactive support could be extended in the future to support a "pull" model.
36
+
* Red's reactive support could be extended in the future to also support a "pull" model.
38
37
* This is not a [FRP](https://en.wikipedia.org/wiki/Functional_reactive_programming) framework, though event streams could be supported in the future.
39
-
* The Red/View GUI engine relies on *face!* objects in order to operate graphic objects. Faces are reactors, and they can be used for setting reactive relations between them or with non-reactor objects.
38
+
* The Red/View GUI engine relies on *face!* objects in order to operate graphic objects. Faces are reactors, and they can be used for setting reactive relations between faces or with non-reactor objects.
40
39
41
40
## Glossary
42
41
43
42
Expression | Definition
44
43
---------- | ----------
45
-
**reactive programming** | A programming paradigm, subset of dataflow programming, relying on events "pushing" changes.
46
-
**reaction**| A block of code which contains one or more reactive expressions.
44
+
**reactive programming** | A programming paradigm, a subset of dataflow programming, based on events "pushing" changes.
45
+
**reaction**| A block of code which contains one or more reactive expressions.
47
46
**reactive expression** | An expression which references at least one reactive source.
48
-
**reactive relation** | A relation between two or more objects implemented using reactive expression(s).
49
-
**reactive source** | A path! value referring to an reactive object field.
47
+
**reactive relation** | A relation between two or more objects implemented using reactive expressions.
48
+
**reactive source** | A path! value referring to a field in a reactive object.
50
49
**reactive formula** | A reaction which returns the last expression result on evaluation.
51
50
**reactive object** | An object whose fields can be used as reactive sources.
52
-
**reactor**| Alias for "reactive object".
51
+
**reactor** | Alias for "reactive object".
53
52
54
53
## Static Relations
55
54
@@ -62,17 +61,17 @@ The simplest form of reactions is a "static relation" created between *named* ob
62
61
b: base react [b/color/1: to integer! 255 * s/data]
63
62
]
64
63
65
-
This example sets a reactive relation between a slider named `s` and a base face named `b`. When the slider is moved, the base face's background red component is changed accordingly. The reactive expression cannot be re-used for a different set of faces. This is the simplest form of reactive behavior you can set for graphic objects in Red/View.
64
+
This example sets a reactive relation between a slider named `s` and a base face named `b`. When the slider is moved, the base face's background red component is changed accordingly. The reactive expression cannot be re-used for a different set of faces. This is the simplest form of reactive behavior for graphic objects in Red/View.
This example is not related to the GUI system. It calculates the length of a vector defined by `vec/x` and `vec/y` using a reactive expression. Once again, the source object is statically specified, using its name (`vec`) in the reactive expression.
73
-
74
71
Another form of static relation can be defined using the `is` operator, where the value of the reaction evaluation is set to a word (in any context).
75
72
73
+
This example is not related to the GUI system. It calculates the length of a vector defined by `vec/x` and `vec/y` using a reactive expression. Once again, the source object is statically specified, using its name (`vec`) in the reactive expression.
74
+
76
75
**Example 3**
77
76
78
77
a: make reactor! [x: 1 y: 2 total: is [x + y]]
@@ -84,17 +83,17 @@ The word `total` above has its value set to the `x + y` expression. Each time th
84
83
a: make reactor! [x: 1 y: 2]
85
84
total: is [a/x + a/y]
86
85
87
-
This variation of Example 3 shows that a global word can also be the target of a reactive relation (though it can't be the source). This form is the closest to a spreadsheet's (e.g. Excel) formula model.
86
+
This variation of Example 3 shows that a global word can also be the target of a reactive relation (though it can't be the source). This form is the closest to that of a spreadsheet's (e.g. Excel) formula model.
88
87
89
-
Note: due to the size of global context, making it reactive could have significant performance overhead, though that could be overcome in the future.
88
+
Note: due to the size of global context, making it reactive (as above with `total`) could have significant performance overhead, though that could be overcome in the future.
90
89
91
90
## Dynamic Relations
92
91
93
-
Static relations are very easy to specify, but they don't scale well if you need to provide the same reaction to a number of reactors, or if the reactors are anonymous (reminder: all objects are anonymous by default). In such cases, the reaction should be specified using a *function* and `react/link`.
92
+
Static relations are easy to specify, but they don't scale well if you need to provide the same reaction to a number of reactors, or if the reactors are anonymous (reminder: all objects are anonymous by default). In such cases, the reaction should be specified using a *function* and `react/link`.
94
93
95
94
**Example**
96
95
97
-
;-- Drag the red ball up and down with the mouse and see how other balls react!
96
+
;-- Drag the red ball up and down with the mouse. Watch how the other balls react.
98
97
99
98
win: layout [
100
99
size 400x500
@@ -113,9 +112,7 @@ Static relations are very easy to specify, but they don't scale well if you need
113
112
]
114
113
view win
115
114
116
-
In this example, the reaction is a function (`follow`) which is applied to the ball faces by pairs, creating a chain of relations, linking all the balls together. The terms in the reaction are parameters, so the can be used for different objects (unlike in the static relations case).
117
-
118
-
To see how it works, paste the above example into the GUI console and drag the red ball up and down.
115
+
In this example, the reaction is a function (`follow`) which is applied to the ball faces by pairs, creating a chain of relations, linking all the balls together. The terms in the reaction are parameters, so they can be used for different objects (unlike static relations).
119
116
120
117
121
118
# API
@@ -141,22 +138,20 @@ To see how it works, paste the above example into the GUI console and drag the r
141
138
142
139
**Description**
143
140
144
-
Sets a new reactive relation which contains at least one reactive source, from:
145
-
* a block of code (sets a "static relation")
146
-
* a function (sets a "dynamic relation", requires the `/link` refinement)
141
+
`react` sets a new reactive relation, which contains at least one reactive source, from a block of code (sets a "static relation") or a function (sets a "dynamic relation" and requires the `/link` refinement). In both cases, the code is statically analyzed to determine the reactive sources (in the form of path! values) referring to reactor fields.
147
142
148
-
In both cases, the code is statically analyzed to determine the reactive sources, in the form of path! values, referring to reactor fields. The newly formed reaction **is called once** on creation (before the `react` function returns). This default behavior can be undesirable in some cases, this initial triggering can be avoided using the `/later` option.
143
+
By default, the newly formed reaction **is called once on creation**before the `react` function returns. This can be undesirable in some cases, so can be avoided by using the `/later` option.
149
144
150
-
A reaction can contain arbitrary Red code, have one or several reactive sources, one or several reactive expressions. It is up to the user to determine the granularity of relations to set up, which best fits his use-cases.
145
+
A reaction contains arbitrary Red code, one or more reactive sources, and one or more reactive expressions. It is up to the user to determine the set of relations which best fit their needs.
151
146
152
147
The `/link` option takes a function as the reaction and a list of arguments objects to be used when evaluating the reaction. This alternative form allows dynamic reactions, where the reaction code can be reused with different sets of objects (the basic `react` can only work with statically *named* objects).
153
148
154
-
Removing a reaction is achieved by using `/unlink` refinement with a `<source>` argument which can take the following values:
155
-
*`'all` word, will remove all reactive relations created by the reaction.
156
-
*an object value, will remove only relations where that object is the reactive source.
157
-
*a list of objects, will remove only relations where those objects are the reactive source.
149
+
A reaction is removed by using the `/unlink` refinement with one of the following as a `<source>` argument:
150
+
*The `'all` word, will remove all reactive relations created by the reaction.
151
+
*An object value, will remove only relations where that object is the reactive source.
152
+
*A list of objects, will remove only relations where those objects are the reactive source.
158
153
159
-
`/unlink` takes a reaction block or function as argument, so only relations created from *that* reaction will be removed.
154
+
`/unlink` takes a reaction block or function as argument, so only relations created from *that* reaction are removed.
160
155
161
156
## is
162
157
@@ -169,9 +164,9 @@ Removing a reaction is achieved by using `/unlink` refinement with a `<source>`
169
164
170
165
**Description**
171
166
172
-
The `is`operator creates a reactive formula, whose result will be assigned to a word. The `<code>` block can contain reference to both wrapping object's fields (if used in a reactor's body block), and external reactors fields.
167
+
`is` creates a reactive formula whose result will be assigned to a word. The `<code>` block can contain references to both the wrapping object's fields, if used in a reactor's body block, and to external reactor's fields.
173
168
174
-
Note: this operator creates reactive formula which are very close to Excel's formula model.
169
+
Note: This operator creates reactive formulas which closely mimic Excel's formula model.
175
170
176
171
**Example**
177
172
@@ -196,7 +191,7 @@ Note: this operator creates reactive formula which are very close to Excel's for
196
191
197
192
**Description**
198
193
199
-
Checks if an object's field is a reactive source. If it is true, then the first reaction found where that object's field is present will be returned, otherwise `none` is returned.
194
+
`react?` checks if an object's field is a reactive source. If it is, the first reaction found where that object's field is present will be returned, otherwise `none` is returned.
200
195
201
196
## clear-reactions
202
197
@@ -206,7 +201,7 @@ Checks if an object's field is a reactive source. If it is true, then the first
206
201
207
202
**Description**
208
203
209
-
Removes all defined reactions unconditionally.
204
+
Removes all defined reactions, unconditionally.
210
205
211
206
## dump-reactions
212
207
@@ -216,7 +211,7 @@ Removes all defined reactions unconditionally.
216
211
217
212
**Description**
218
213
219
-
Output a list of registered reactions for debugging purpose.
214
+
Outputs a list of registered reactions for debugging purposes.
220
215
221
216
# Reactive Objects
222
217
@@ -234,9 +229,9 @@ Ordinary objects in Red do not exhibit reactive behaviors. In order for an objec
234
229
235
230
**Description**
236
231
237
-
Constructs a new reactive object from the body block. Only setting a field to a new value can trigger reactions (if defined for that field).
232
+
Constructs a new reactive object from the body block. In the returned object, setting a field to a new value will trigger reactions defined for that field.
238
233
239
-
Note: The body block can eventually contain `is` expressions.
234
+
Note: The body may contain `is` expressions.
240
235
241
236
## deep-reactor!
242
237
@@ -250,6 +245,21 @@ Note: The body block can eventually contain `is` expressions.
250
245
251
246
**Description**
252
247
253
-
Constructs a new reactive object from the body block. Setting a field to a new value or changing a referred series deeply can trigger reactions (if defined for that field).
248
+
Constructs a new reactive object from the body block. In the returned object, setting a field to a new value or changing a series the field refers to, including nested series, will trigger reactions defined for that field.
249
+
250
+
Note: The body may contain `is` expressions.
251
+
252
+
**Example**
253
+
254
+
This shows how changing a series, even a nested one, triggers a reaction.
255
+
256
+
Note: It is up to the user to prevent triggering cycles at this time. For example, if a `deep-reactor!` changes series values in a reactor formula (e.g. `is`), it may create endless reaction cycles.
254
257
255
-
Note: The body block can eventually contain `is` expressions.
0 commit comments