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
Once you have a `Callback` you can run it manually if you need, by calling `.runNow()`.
59
+
It isn't necessary and you shouldn't do it because scalajs-react handles it for you to ensure things run at the right time
60
+
on the right threads, but if you ever want to, you can.
61
+
62
+
#### Fusion via `>>`
63
+
64
+
The `>>` operator deserves a special mention as it's commonly useful.
65
+
It's used to fuse to callbacks together sequentially.
66
+
It's like a pure version of `;` which is how you sequence statements imperatively.
67
+
68
+
```scala
69
+
defgreet:Callback=
70
+
Callback {
71
+
println("Hello.")
72
+
println("Goodbye.")
73
+
}
74
+
75
+
// This ↑ is equivalent to this ↓
76
+
77
+
defgreet:Callback= {
78
+
valhello=Callback(println("Hello."))
79
+
valbye=Callback(println("Goodbye."))
80
+
hello >> bye
81
+
}
82
+
83
+
// which is equivalent to this ↓
84
+
85
+
defgreet:Callback= {
86
+
valhello=Callback(println("Hello."))
87
+
valbye=Callback(println("Goodbye."))
88
+
hello.flatMap(_ => bye)
89
+
}
90
+
```
91
+
92
+
If you're wondering why `>>`, it's a convention used in various other monadic libraries.
93
+
I like to read it like a pipeline where the arrows show control flow.
94
+
This ↓ shows that `a` is run, then it flows right to run `b`, then flows right to run `c`.
95
+
96
+
```scala
97
+
a >> b >> c
98
+
```
99
+
100
+
Now let me also introduce `>>=` which is an alias for `flatMap`. As we know, `flatMap` takes an argument. The signature in a `CallbackTo[A]` is `def flatMap[B](f: A => CallbackTo[B]): CallbackTo[B]`. Now consider this example:
101
+
102
+
```scala
103
+
a >> b >>= c
104
+
```
105
+
106
+
It still looks like a pipeline but this time there is a `=` symbol popping out which you could imagine spits out a value.
107
+
The flow is still intact (`a` to `b` to `c`) except this time we know that `c` takes the output of `b`. If we expand that example into real code, it looks like this:
108
+
109
+
```scala
110
+
vala=Callback(println("Start"))
111
+
valb=CallbackTo(300)
112
+
valc= (i: Int) =>Callback(println("Input = "+ i))
113
+
114
+
valx= a >> b >>= c
115
+
116
+
x.runNow()
117
+
// Start
118
+
// Input = 300
119
+
```
120
+
121
+
#### Monadic Learning Curve
122
+
123
+
Working with `Callback`/`CallbackTo` might seem odd if you're not used to capturing effects with monads, but it's a transferable skill with applications outside of `Callback` itself.
124
+
125
+
If you'd like to learn more about this approach, see *How to declare an imperative* by Philip Wadler.
126
+
<br>A summary is available here: https://www.dcc.fc.up.pt/~pbv/aulas/tapf/slides/imperative.html
127
+
128
+
A direct example of how *this* connects to *that*, is the **Equational reasoning** example.
129
+
<br>Say we have a callback that prints "ha" twice to display "haha".
because `Callback` is referentially-transparent, and is the representation of an action instead of the result of an action,
136
+
we can do reduce duplication by doing this:
137
+
138
+
```scala
139
+
valha=Callback(print("ha"))
140
+
valhaha2= ha >> ha
141
+
```
142
+
143
+
Because equational reasoning holds, both callbacks are equivalent.
144
+
```
145
+
scala> haha1.runNow()
146
+
haha
147
+
scala> haha2.runNow()
148
+
haha
149
+
```
150
+
151
+
If you're getting started and find monads hard, remember you can start by just wrapping your imperative code.
152
+
So instead of:
153
+
```scala
154
+
defspeak():Unit= {
155
+
println("Hello!")
156
+
println("Goodbye...")
157
+
}
158
+
```
159
+
you can wrap it like:
160
+
```scala
161
+
defspeak=Callback {
162
+
println("Hello!")
163
+
println("Goodbye...")
164
+
}
165
+
```
166
+
167
+
Notice that we change `speak()` into `speak` as it's now pure.
168
+
<br>Also be careful to call `.runNow()` on any inner callbacks if you take this approach. If you don't, scalac will just throw it away without executing it which is probably not what you want -- Scala does all kinds of nasty things when `Unit` is involved which is what `;` does between imperative statements.
169
+
170
+
It's actually recommended that you *not* take this approach and instead, use proper operators to combine callbacks as the compiler will be able to offer help and catch problems.
Once you have a `Callback` you can run it manually if you need, by calling `.runNow()`.
263
-
It isn't necessary and you shouldn't do it because scalajs-react handles it for you to ensure things run at the right time
264
-
on the right threads, but if you ever want to, you can.
265
-
266
-
#### Fusion via `>>`
267
-
268
-
The `>>` operator deserves a special mention as it's commonly useful.
269
-
It's used to fuse to callbacks together sequentially.
270
-
It's like a pure version of `;` which is how you sequence statements imperatively.
271
-
272
-
```scala
273
-
defgreet:Callback=
274
-
Callback {
275
-
println("Hello.")
276
-
println("Goodbye.")
277
-
}
278
-
279
-
// This ↑ is equivalent to this ↓
280
-
281
-
defgreet:Callback= {
282
-
valhello=Callback(println("Hello."))
283
-
valbye=Callback(println("Goodbye."))
284
-
hello >> bye
285
-
}
286
-
287
-
// which is equivalent to this ↓
288
-
289
-
defgreet:Callback= {
290
-
valhello=Callback(println("Hello."))
291
-
valbye=Callback(println("Goodbye."))
292
-
hello.flatMap(_ => bye)
293
-
}
294
-
```
295
-
296
-
If you're wondering why `>>`, it's a convention used in various other monadic libraries.
297
-
I like to read it like a pipeline where the arrows show control flow.
298
-
This ↓ shows that `a` is run, then it flows right to run `b`, then flows right to run `c`.
299
-
300
-
```scala
301
-
a >> b >> c
302
-
```
303
-
304
-
Now let me also introduce `>>=` which is an alias for `flatMap`. As we know, `flatMap` takes an argument. The signature in a `CallbackTo[A]` is `def flatMap[B](f: A => CallbackTo[B]): CallbackTo[B]`. Now consider this example:
305
-
306
-
```scala
307
-
a >> b >>= c
308
-
```
309
-
310
-
It still looks like a pipeline but this time there is a `=` symbol popping out which you could imagine spits out a value.
311
-
The flow is still intact (`a` to `b` to `c`) except this time we know that `c` takes the output of `b`. If we expand that example into real code, it looks like this:
312
-
313
-
```scala
314
-
vala=Callback(println("Start"))
315
-
valb=CallbackTo(300)
316
-
valc= (i: Int) =>Callback(println("Input = "+ i))
317
-
318
-
valx= a >> b >>= c
319
-
320
-
x.runNow()
321
-
// Start
322
-
// Input = 300
323
-
```
324
-
325
-
#### Monadic Learning Curve
326
-
327
-
Working with `Callback`/`CallbackTo` might seem odd if you're not used to capturing effects with monads, but it's a transferable skill with applications outside of `Callback` itself.
328
-
329
-
If you'd like to learn more about this approach, see *How to declare an imperative* by Philip Wadler.
330
-
<br>A summary is available here: https://www.dcc.fc.up.pt/~pbv/aulas/tapf/slides/imperative.html
331
-
332
-
A direct example of how *this* connects to *that*, is the **Equational reasoning** example.
333
-
<br>Say we have a callback that prints "ha" twice to display "haha".
because `Callback` is referentially-transparent, and is the representation of an action instead of the result of an action,
340
-
we can do reduce duplication by doing this:
341
-
342
-
```scala
343
-
valha=Callback(print("ha"))
344
-
valhaha2= ha >> ha
345
-
```
346
-
347
-
Because equational reasoning holds, both callbacks are equivalent.
348
-
```
349
-
scala> haha1.runNow()
350
-
haha
351
-
scala> haha2.runNow()
352
-
haha
353
-
```
354
-
355
-
If you're getting started and find monads hard, remember you can start by just wrapping your imperative code.
356
-
So instead of:
357
-
```scala
358
-
defspeak():Unit= {
359
-
println("Hello!")
360
-
println("Goodbye...")
361
-
}
362
-
```
363
-
you can wrap it like:
364
-
```scala
365
-
defspeak=Callback {
366
-
println("Hello!")
367
-
println("Goodbye...")
368
-
}
369
-
```
370
-
371
-
Notice that we change `speak()` into `speak` as it's now pure.
372
-
<br>Also be careful to call `.runNow()` on any inner callbacks if you take this approach. If you don't, scalac will just throw it away without executing it which is probably not what you want -- Scala does all kinds of nasty things when `Unit` is involved which is what `;` does between imperative statements.
373
-
374
-
It's actually recommended that you *not* take this approach and instead, use proper operators to combine callbacks as the compiler will be able to offer help and catch problems.
0 commit comments