-
Notifications
You must be signed in to change notification settings - Fork 15
Description
We can leverage Racket's bindings at the top level of Qi flows, but don't have a way to name intermediate values produced in flows, without decomposing the flows themselves and naming the results of each component using Racket definition forms like define and let.
The other option available now is to use "control" inputs, that is, pass parameters for a flow specification as runtime inputs to the flow. This option is perhaps equally expressive, but in some cases it is more complicated than using bindings would be.
Examples
Here are some examples illustrating what bindings in Qi might look like:
- Accumulating "state" as a side effect.
(~> (5)
(-< _ (~> list (as S))) ; `as` produces no output so only one value flows
(-< sqr (~>> list (append S) (as S)))
(-< add1 (~>> list (append S) (as S))))
- Equivalence with Racket's lambda:
(map (flow (~> (as args) (gen args) ...)) my-list)
equivalent to
(map (λ args (~> ...)) my-list)
- Naming exceptions:
(try flo [(as exn:fail err) handler-flo])
(Note: this syntax conflicts with the use of as elsewhere.)
Context: #29
More generally, the ability to introduce Qi-native bindings in this way allows us to name intermediate values computed in a flow, providing an alternative to the use of "control" inputs to parametrize flow specifications (and would allow us to do this syntactically instead -- e.g. (~> (6) ... (as n) (feedback n add1)) instead of (~> (-< 5 (gen (flow add1))) feedback). See #34 .
Bindings syntax options
(as v w)
(as v . args) ; probably can't because dot is special
(as . args) ; probably can't because dot is special
(as* v args)
(as* args)
Implementation
Could we embed Racket's pattern matching language (match) into Qi to get bindings with minimal effort? It might not be as flexible in terms of scoping rules though. Just an option to keep in mind, maybe even just as an initial version.