Skip to content
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.

Feature PP (pipelines with implicit head) seems weakly motivated #21

Closed
tabatkins opened this issue Mar 21, 2018 · 5 comments
Closed

Feature PP (pipelines with implicit head) seems weakly motivated #21

tabatkins opened this issue Mar 21, 2018 · 5 comments
Assignees
Labels
discussion Discussion about a design decision explainer/readme About readme.md spec About spec.html

Comments

@tabatkins
Copy link

tabatkins commented Mar 21, 2018

I'm struggling to see the reasoning for feature PP. Adding it lets people save exactly one character whenever it's used, but introduces ASI hazards and, imo, makes things look slightly more confusing in general. (I find myself looking for the topic in the examples that use it, then realizing that there is no topic and inferring that it's using PP.)

If you're not paying close attention to things, you can accidentally miss that something is a nested prefix pipeline - x |> foo + ( |> bar(#) ) can, depending on formatting, be mistaken for x |> foo |> bar(#).

If I'm not mistaken, this also allows topic-form to not include a #: x |> (|> bar) would use the outer topic, but wouldn't express it literally. Catch-22 here: if this is valid, it breaks the expectation that topic-form always has a # in it; if it's not valid, it's a confusing instance where prefix-pipeline can't be used due to surrounding context. (That is, x |> # + (|> bar) would be valid, so the error depends on surrounding context.)

It also complicates the variadic-handling of pipeline functions, as you note in #4 (comment).

I also think it ends up being somewhat confusing with pipeline-functions; both of them start with a pipeline-ish operator, but one creates a function to obtain the topic, the other just immediately uses the surrounding topic. In other words, I see xs.map(|> foo) being a footgun with PP, where the author meant xs.map(+> foo). Without PP this is a syntax error as written; if correctly written as xs.map(# |> foo), it's much more obvious what's happening.

(I can't find the link right now, but at least one person in the pipeline-proposal repo was asking for |> foo to automatically create a pipeline function, so the confusion is already possible.)

Overall, I just don't see the particular value of being able to omit the # from the beginning of a pipeline, considering the downsides.

@js-choi
Copy link
Collaborator

js-choi commented Mar 21, 2018

@tabatkins: Thanks for the valuable feedback!

Adding it lets people save exactly one character whenever it's used, but introduces ASI hazards and, imo, makes things look slightly more confusing in general. (I find myself looking for the topic in the examples that use it, then realizing that there is no topic and inferring that it's using PP.)

This is understandable; in fact, I had already been considering dropping it too. The ASI hazard in particular has been concerning to me.

If you're not paying close attention to things, you can accidentally miss that something is a nested prefix pipeline - x |> foo + ( |> bar(#) ) can, depending on formatting, be mistaken for x |> foo |> bar(#).

This makes sense.

If I'm not mistaken, this also allows topic-form to not include a #: x |> (|> bar) would use the outer topic, but wouldn't express it literally. Catch-22 here: if this is valid, it breaks the expectation that topic-form always has a # in it; if it's not valid, it's a confusing instance where prefix-pipeline can't be used due to surrounding context. (That is, x |> # + (|> bar) would be valid, so the error depends on surrounding context.)

If Feature PP is active, then this example would indeed be valid. A prefix pipeline would count as a usage of the topic, which in turn would make x|> (|> bar) valid and equivalent to x |> bar.

It also complicates the variadic-handling of pipeline functions, as you note in #4 (comment).

This complication wasn’t bad. In general, a headless pipeline |> bar would be equivalent to ... |> bar.

I also think it ends up being somewhat confusing with pipeline-functions; both of them start with a pipeline-ish operator, but one creates a function to obtain the topic, the other just immediately uses the surrounding topic. In other words, I see xs.map(|> foo) being a footgun with PP, where the author meant xs.map(+> foo). Without PP this is a syntax error as written; if correctly written as xs.map(# |> foo), it's much more obvious what's happening.

Excellent point.

(I can't find the link right now, but at least one person in the pipeline-proposal repo was asking for |> foo to automatically create a pipeline function, so the confusion is already possible.)

That would be tc39/proposal-pipeline-operator#96.

Overall, I just don't see the particular value of being able to omit the # from the beginning of a pipeline, considering the downsides.

These downsides are considerable. I agree with you, particularly with the visual-confusability problem of prefix |> and prefix +> (distinguishable punctuators is an important goal).

Let’s drop Feature PP.

@js-choi js-choi self-assigned this Mar 21, 2018
@js-choi
Copy link
Collaborator

js-choi commented Mar 22, 2018

@tabatkins: One of the primary advantages of headless pipelines is that they may make data flow clearer with statements such as … |> { if (# > 0) |> foo; else |> bar; } |> …, but that might also be doable with pipeline versions of if statements, like what Feature TP is proposing with try |>, catch |>, and finally |>.

@js-choi
Copy link
Collaborator

js-choi commented Mar 22, 2018

Another plus that headless |> brought was that—since +> |> bar cancels out into +> bar, indentation for this:

const toSlug =
  +> #.split(' ')
  |> #.map(+> #.toLowerCase())
  |> #.join('-')
  |> encodeURIComponent;

…could line up like this:

const toSlug = +>
|> #.split(' ')
|> #.map(+> #.toLowerCase())
|> #.join('-')
|> encodeURIComponent;

This aesthetic advantage probably does not outweigh the disadvantages enumerated above.


Edit: It should also be noted that the hypothesized headless ::foo binding syntax for #::foo also suffers from the valid-topic-style-without-visible-topic-reference problem. Its examples it also need to be removed for later reconsideration.

@tabatkins
Copy link
Author

Regarding the wrapping aesthetics, one could always do:

const toSlug = +> #
|> #.split(' ')
|> #.map(+> #.toLowerCase())
|> #.join('-')
|> encodeURIComponent;

if one really wanted to line up the pipelines perfectly on the left without the pipe-function messing up their straight vertical line. ^_^

@js-choi
Copy link
Collaborator

js-choi commented Mar 22, 2018

Yes. This too:

const toSlug =
+> #.split(' ')
|> #.map(+> #.toLowerCase())
|> #.join('-')
|> encodeURIComponent;

…probably also works fine, heh. Anyways, Feature PP has been removed.

@js-choi js-choi added explainer/readme About readme.md spec About spec.html discussion Discussion about a design decision labels Mar 24, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
discussion Discussion about a design decision explainer/readme About readme.md spec About spec.html
Projects
None yet
Development

No branches or pull requests

2 participants