-
Notifications
You must be signed in to change notification settings - Fork 109
Open
Labels
follow-on proposalDiscussion about a future follow-on proposalDiscussion about a future follow-on proposal
Description
This is a spinoff of #311 (comment) and #159.
- In many contexts, such as query building, pipes oftentimes may need to do repetitive computations or queries. These contexts include:
- Optional chaining (Optional chaining support for the pipeline operator? #159 and Optional Hackpipes proposal #198).
- Observables.
- Database queries (e.g., SQL, LINQ).
- Parser combinators.
- Data sources like Facebook’s Haxl.
- (I wrote this issue in a hurry, so the above use cases need specific code examples later, maybe from my old context blocks proposal.)
- Railway-oriented programming:
- Many of these contexts share a common pattern.
- Their computations generally run on a “happy path”.
- But there is an alternative track that needs to be handled differently (such as expected operational exceptions).
- This is sometimes called “railway-oriented programming” in F# and C#.
- In JavaScript…
- If the pipeline (or “railway”) is simple, with only one (synchronous) happy path and no special processing on each step, then simple assignment to temporary variables works (Deeply nested expressions A(B(C(D(E(…), …), …), …), …) vs. temp variables #311).
- 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#’s solution:
- F# has solved this using query expressions and its other computation expressions.
- 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 were inspired by F# computation expressions and other languages’ monadic do-notation.
- 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 encompass the inactive
do
expressions andasync do
expressions. - 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.
- They would functionally act quite similar to the idea in Placeholder name, eg %name #274.
- 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(#)
, wheremaybe
is a variable containing a “maybe monad” that would cause the pipeline to evaluatef(#)
only ifintOrNullValue
is not nullish. - Context pipes could create complex query scaffolding at each step of the pipeline.
- Context pipes would cover optional pipes (Optional chaining support for the pipeline operator? #159 and Optional Hackpipes proposal #198), which are just context pipes using a maybe monad.
- They would also support custom contexts like LINQ query building.
- These “context” pipe operators that apply a monad or some other kind of custom “context” to a pipe, like
- But, this is for a far-future add-on proposal.
- These are just half-formed ideas right now.
- The Committee has become very generally chilly towards any new syntax.
- This has become especially uncertain with the recent JS0/JSSugar proposal.
- There is no way that we can feasibly advance a more complicated pipe, let alone context pipes or context blocks.
- That’s much of why I haven’t spent time on them.
- If you want to discuss LINQ-like “customized” context pipelines here, or “context blocks”, or monads in general, feel free to discuss them here.
helena-muniz
Metadata
Metadata
Assignees
Labels
follow-on proposalDiscussion about a future follow-on proposalDiscussion about a future follow-on proposal