-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suggestion: instead use as sugar for a new Array.prototype.pipe #177
Comments
@samhh Could you share what you find confusing? I would like to clarify. |
Hey @dustbort. Sorry for that reaction, it was a lazy one whilst I ticked through my list of GitHub notifications this morning. The most fundamental criticism I can offer is that as an fp-ts user who uses pipe(x, foo(f), bar, baz(g)) In my view, this proposal is more noisy and as a result less readable, and, though this could just be due to unfamiliarity, the underlying array behaviour is not intuitive. It's as far as I know different to pipelines in every other language. As for nullability, I believe the first step should be to encourage userland helpers. This is in essence what I and many others already do with types like x |> foo |> nullMap(bar) |> nullMap(baz)
// or
x |> foo |> nullMap(y => y |> bar |> baz) I'm not convinced that choosing a path forward for pipelines should be determined by trying to shoehorn in preexisting operators, and picking a style that in my view functional programmers aren't even likely to use is questionable. But I can't speak for anyone else, so more perspectives would be helpful. |
JavaScript doesn't offer currying, and this proposal doesn't introduce it.
No. If that were the case, then F# wouldn't have operators for each arity. Plus, it is easy to simulate currying for partial application using arrow functions:
True, but what about having an operator for each arity? Can't we do better? The array behavior is to make a scalar into a 1-tuple, which makes
Regarding noise, your example here looks noisy. And I don't see short-circuiting.
JavaScript doesn't have Option, and this proposal doesn't introduce it. Optional chaining |
You can curry in JavaScript manually by just returning a series of unary functions. The short-circuiting in my example would be |
Of course, as in any language. How does that address the issue?
That's not short circuiting. It's still going to execute every step in the chain, although each step will just be checking if it is nullish, but that's the whole point of short-circuiting with optional chaining. |
I think we're now arguing about semantics. The behaviour for the end user is the same, except in my case where you define that behaviour yourself it's more flexible and, as I've said, more fundamentally useful for the developers most likely to utilise pipelines at all. |
The semantics of optional chaining is a key part of the issue, to cover a common case. Would you find the following operator semantics more intuitive? Now
The actual implementation of the operators can be optimized to eliminate superfluous use of arrays. You're free not to use |
I wouldn't personally add anything except |
Thanks for your input. After rereading through the issues for this proposal, I can simply suggest |
I have read a lot of discussion about pipeline operator and variants like optional pipeline
?>
. I also know this can lead down a rabbit hole with 2- and 3-arity pipeline operators as in F#: |>, ||>, |||>, <|, <||, <|||. I have a suggestion to avoid these and allow pipeline to cover many more use cases.What if we define a new function on Array.prototype called
pipe
that works as follows?pipe
will operate on an array and spread the elements of the array as the arguments to a supplied function. If the return value of the applied function is nullish (null or undefined) thenpipe
returns that value as-is; otherwise,pipe
wraps the result in an array. For example:This has the nice property that it works in conjunction with the optional chaining operator
?.
, so that we can short circuit multiple chained pipes when we encounter a nullish return value:What if the applied function returns an n-tuple to which we want to apply a subsequent n-arity transformation with
pipe
? We've wrapped it in an extra array in that case. No problem, let's define another function on Array.prototype calledflatPipe
. It works likepipe
, except it does not wrap the result in an array.Now we can chain
pipe
s andflatPipe
s to our heart's desire, with transformations of any arity using only these two pipeline functions. And we can short-circuit with the existing optional chaining?.
.Let's revisit the proposed pipeline operator in light of
pipe
andflatPipe
. Let's define:a |> b
:=a.pipe(b)
a ?|> b
:=a?.pipe(b)
a |>> b
:=a.flatPipe(b)
a ?|>> b
:=a?.flatPipe(b)
This is very nice. The benefit of having to wrap a scalar value in an array in the 1-arity case is that we don't define the pipeline operator based on the exact arity of the tuple, only whether it is returned as a scalar or a tuple. This means we can have a 5-arity pipeline without defining
|||||>
, etc. Rather, the operator is chosen based on how we need to adapt the return value of the function to work in a pipeline, either scalar or tuple.The text was updated successfully, but these errors were encountered: