docs/internals: mention Op:setup_out
s-ol
6 months ago
124 | 124 | They are implemented by deriving from the `Op` class and implementing at least |
125 | 125 | the `Op:setup` and `Op:tick` methods. |
126 | 126 | |
127 | import Constant, SigStream, Op, Input, evt from require 'alv.base' | |
127 | import Constant, Op, Input, T, evt from require 'alv.base' | |
128 | 128 | |
129 | 129 | total_sum = Constant.meta |
130 | 130 | meta: |
134 | 134 | description: "Keep a total sum of incoming number events, extension-style." |
135 | 135 | |
136 | 136 | value: class extends Op |
137 | new: (...) => | |
138 | super ... | |
139 | @state or= { total: 0 } | |
140 | @out or= SigStream 'num', @state.total | |
141 | ||
142 | 137 | setup: (inputs, scope) => |
143 | 138 | num = evt.num\match inputs |
139 | ||
144 | 140 | super num: Inputs.hot num |
141 | ||
142 | @state or= { total: 0 } | |
143 | @update_out '~', T.num, @state.total | |
145 | 144 | |
146 | 145 | tick: => |
147 | 146 | @state.total += @inputs.num! |
237 | 236 | constructor and pass on all arguments using `...`. Keep in mind that the |
238 | 237 | Constructor is called not only when an Op is first created, but also to |
239 | 238 | sandbox changes before potentially rolling them back (more on this below). |
240 | ||
241 | In general, setting it `Op.out` in the constructor is preferred, and it is only | |
242 | moved to `Op:setup` if the output type depends on the arguments received. | |
243 | ||
244 | It is best to only recreate `Op.out` and `Op.state` if that is absolutely | |
245 | necessary (e.g. the output type has changed as a result of new inputs). This is | |
246 | so that the Op continues running smoothly without discontinuities when | |
247 | unrelated changes are made. | |
248 | 239 | |
249 | 240 | There are three types of `Result`s that can be created for `Op.out`: |
250 | 241 | |
258 | 249 | `Constant`s directly, as `SigStream`s outputs are automatically |
259 | 250 | 'downgraded' to `Constant`s when the Op has no reactive inputs. |
260 | 251 | |
252 | It is best to only recreate `Op.out` and `Op.state` if that is absolutely | |
253 | necessary (e.g. the output type has changed as a result of new inputs). | |
254 | This is so that the Op continues running smoothly without discontinuities when | |
255 | unrelated changes are made. | |
256 | ||
257 | For this reason, in most cases `Op.state` should be set up using | |
258 | `@state or= ...`, and `Op.out` with `Op.setup_state`: | |
259 | ||
260 | setup: => | |
261 | @state or= 0 | |
262 | @setup_out '~', T.num, 2 | |
263 | ||
264 | Sometimes `Op.state` depends on the output type and needs to be reset when that | |
265 | changes. When the output was recreated, `Op.setup_out` returns `true`. | |
266 | ||
261 | 267 | ### Op:tick |
262 | 268 | `Op:tick` is called whenever any of the inputs are *dirty*. This is where the |
263 | 269 | Op's main logic will go. Generally here it should be checked which input(s) |