Skip to content

Commit 5cb78d4

Browse files
committed
Merge branch 'master' of github.com:red/docs
2 parents cf529f7 + d8470d8 commit 5cb78d4

File tree

1 file changed

+49
-39
lines changed

1 file changed

+49
-39
lines changed

reactivity.md

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616

1717
# Concept
1818

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

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

2323
<div style="text-align:center"><img src="images/react-simple.png" /></div>
2424

@@ -28,28 +28,27 @@ If the description seems a bit abstract, don't worry, the reactive API and its u
2828

2929
*Graphs C, D & E show chained reactions, where some targets are, themselves, reactors, setting up a chain of relations that can have any shape.*
3030

31-
3231
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`.
3332

3433
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.
3534

3635
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.
3837
* 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.
4039

4140
## Glossary
4241

4342
Expression | Definition
4443
---------- | ----------
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.
4746
**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.
5049
**reactive formula** | A reaction which returns the last expression result on evaluation.
5150
**reactive object** | An object whose fields can be used as reactive sources.
52-
**reactor** | Alias for "reactive object".
51+
**reactor** | Alias for "reactive object".
5352

5453
## Static Relations
5554

@@ -62,17 +61,17 @@ The simplest form of reactions is a "static relation" created between *named* ob
6261
b: base react [b/color/1: to integer! 255 * s/data]
6362
]
6463

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

6766
**Example 2**
6867

6968
vec: make reactor! [x: 0 y: 10]
7069
box: object [length: is [square-root (vec/x ** 2) + (vec/y ** 2)]]
7170

72-
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-
7471
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).
7572

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+
7675
**Example 3**
7776

7877
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
8483
a: make reactor! [x: 1 y: 2]
8584
total: is [a/x + a/y]
8685

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

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

9190
## Dynamic Relations
9291

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`.
9493

9594
**Example**
9695

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

9998
win: layout [
10099
size 400x500
@@ -113,9 +112,7 @@ Static relations are very easy to specify, but they don't scale well if you need
113112
]
114113
view win
115114

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).
119116

120117

121118
# API
@@ -141,22 +138,20 @@ To see how it works, paste the above example into the GUI console and drag the r
141138

142139
**Description**
143140

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

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

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

152147
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).
153148

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

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

161156
## is
162157

@@ -169,9 +164,9 @@ Removing a reaction is achieved by using `/unlink` refinement with a `<source>`
169164

170165
**Description**
171166

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

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

176171
**Example**
177172

@@ -196,7 +191,7 @@ Note: this operator creates reactive formula which are very close to Excel's for
196191

197192
**Description**
198193

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

201196
## clear-reactions
202197

@@ -206,7 +201,7 @@ Checks if an object's field is a reactive source. If it is true, then the first
206201

207202
**Description**
208203

209-
Removes all defined reactions unconditionally.
204+
Removes all defined reactions, unconditionally.
210205

211206
## dump-reactions
212207

@@ -216,7 +211,7 @@ Removes all defined reactions unconditionally.
216211

217212
**Description**
218213

219-
Output a list of registered reactions for debugging purpose.
214+
Outputs a list of registered reactions for debugging purposes.
220215

221216
# Reactive Objects
222217

@@ -234,9 +229,9 @@ Ordinary objects in Red do not exhibit reactive behaviors. In order for an objec
234229

235230
**Description**
236231

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

239-
Note: The body block can eventually contain `is` expressions.
234+
Note: The body may contain `is` expressions.
240235

241236
## deep-reactor!
242237

@@ -250,6 +245,21 @@ Note: The body block can eventually contain `is` expressions.
250245

251246
**Description**
252247

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

255-
Note: The body block can eventually contain `is` expressions.
258+
r: make deep-reactor! [
259+
x: [1 2 3]
260+
y: [[a b] [c d]]
261+
total: is [append copy x copy y]
262+
]
263+
append r/y/2 'e
264+
print mold r/total
265+

0 commit comments

Comments
 (0)