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
If there is an alternative non-happy path, any asynchrony is involved, or there is special processing on any state, then the pipeline cannot use simple variable assignment.
In that case, it must use nested callbacks / continuations / IIFEs (forming deeply nested pyramids of doom.
Each consecutive inner callback is a step in the pipeline.
The parameter of each consecutive inner callback is the argument to its following steps.
Haskell’s solution (as well as those of many other functional programming languages) includes functor applicators, monads, monoids, arrows, and so on.
F# uses its query expressions to support LINQ, as well as LINQ-like syntax in other contexts.
In actuality, F# query/computation expressions are a clever way to implement monads (and applicator functors and monoids).
There is a deep relationship between Hack pipes and F#’s query expressions and computation expressions (and the LINQ queries they came from, and do-notation, and so on).
F# query/computation expressions flatten deeply nested callbacks (nested continuations or immediately invoked functions / IIFEs), taking their parameters and lining them up in a single linear pipeline.
This is indeed pretty similar to the goals of the ES pipe operator. Even the name “railway-oriented programming” sounds like a more complicated version of “pipeline-oriented programming”.
Years ago, I made an old, abandoned ES “context blocks” proposal for blocks of based on IIFEs.
ES context blocks would allow people to use LINQ-like syntax generically in custom contexts, binding variables to each step of a custom sequence of computations or queries.
ES context blocks would be extensible by the user for creating pipelines in other contexts, like observable/signal chaining, file processing, database queries, parsers, or anything else involving deeply nested callbacks / continuations.
The pipe operator could hypothetically be extended into a customizable “context pipe operator” that uses the same context-block monad infrastructure as context blocks.
These “context” pipe operators that apply a monad or some other kind of custom “context” to a pipe, like intOrNullValue |maybe> f(#), where maybe is a variable containing a “maybe monad” that would cause the pipeline to evaluate f(#) only if intOrNullValue is not nullish.
Context pipes could create complex query scaffolding at each step of the pipeline.
This is a spinoff of #311 (comment) and #159.
doexpressions andasync doexpressions.intOrNullValue |maybe> f(#), wheremaybeis a variable containing a “maybe monad” that would cause the pipeline to evaluatef(#)only ifintOrNullValueis not nullish.