-
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
Proposal 1: Bring back unparen'd arrow functions #104
Comments
Just to reemphasize @mAAdhaTTah’s point: This applies to Proposal 1. This does not apply to the other proposals. The point of this would be to make using arrow functions within pipelines easier, which is important to Proposal 1. However, it would make using pipelines in arrow functions harder. Arrow functions without braces can currently be terminated only by commas and semicolons…I think. This change would amend them to also be terminated by I think the next thing to do here is to sketch the formal grammar—particularly for AssignmentExpression and for ConciseBody. Then we could figure things out from there. If you need any help with interpreting or modifying the spec, @mAAdhaTTah, let me know. |
Personally I'm fine with just making a decision about the precedence like this, but other TC39 members such as @michaelficarra were a bit more hesitant when we discussed this in the past. Even as you're leading this variant, it could be helpful to work to build consensus with as many people as possible; maybe he'd be available to discuss this issue. |
@littledan Yeah, I wasn't sure how controversial this change might be, but given that I think arrow functions are likely to be a common use case for the F#-style pipeline, I think this would be an improvement. Definitely interested in hearing concerns, hence the issue, but I'm not sure who needs to weigh in here. |
I think it'd be good to reach out to the people who expressed concerns previously. What about the other idea to have pipeline placeholders? Didn't we toss around the idea of "backporting" placeholders to the F# proposal, but restricted to be only used in pipelines? |
I don't think anyone has yet expressed concerns about this particular change yet; I haven't seen much of a response to this proposal in general, despite bringing it up a few times, so I'm actually looking for these initial concerns. I do see @charmander 👎 'd this issue, so I'd love to hear from him as to why. I don't think there's anything about the current F# proposal that would preclude that, but it's not included in the F# proposal itself currently, which is intended to be as minimal as possible. Including some form of placeholders in the F# proposal would probably need to determine its relationship with partial application, which is a problem the Smart Pipeline doesn't have, as its implementation is far more expansive than partial application. |
@mAAdhaTTah Many concerns were expressed in #70 . Making the grammar unambiguous fixes the most basic part, but it seemed like most of these concerns were actually about the behavior of making the scope either shorter (as in this proposal) or longer (as I was originally thinking). |
@littledan Ok, I'll take a closer read through there and reach out. Thanks! |
@mAAdhaTTah To be clear, you want arrows to be consistently higher precedence than pipes? That should work. You'd add the pipe production between assignment and sequence. |
@michaelficarra: Yeah, it’d probably be something like displacing the async arrow functions’ nonterminals from
This approach does have important disadvantages, but it might be worth it for the ergonomics of Proposal 1. Don’t yet know. |
cc @zenparsing |
@js-choi That's not putting pipeline lower than assignment. Assuming the a => b |> c Also @mAAdhaTTah, if you do what I described, the downside is pretty steep: you won't be able to assign the result of a pipeline to a variable like this: a = b |> c You'd need parens: a = (b |> c) But I guess that's okay since it's consistent with sequences: a = (b, c) |
@michaelficarra The suggestion is for this: a => b |> c to parse as this: (a => b) |> c but requiring parens around assignment too is tough. This is the kind of thing that would be helpful to get dev feedback on thru the babel plugin. |
@michaelficarra: Yeah, when I realized that making |
l thought the hesitation from |
After editing the README for F# Pipelines, I really dislike requiring parens for assignment. It's used like that all over the place, and I actually think that's worse than requiring parens around arrow functions in the pipeline. I don't know as I want to push out a version in babel that requires parens around assignment and arrow bodies, find out people don't like it, then need to either push out another version of the F# pipeline that reverts this behavior, and push us back to having 4 different proposals again. I think that would be confusing to the community. Besides me, no one else seems like it's a good idea; just that it's worth getting feedback on. So I'm inclined to leave it with the current behavior if we can't resolve assignment issue. I'd be interested in revisiting this if we get the opposite feedback, e.g. that wrapping arrows in pipelines is a hassle. That said, I'm going to dig into the precedence rules and see if there's any way of threading this needle. |
Could we follow @pygy's suggestion, and add a syntax error for unparenthesized expressions? Eg: // syntax error
x => x |> g;
// fine
(x => x) |> g;
x => (x |> g); |
@jridgewell Oh, must have missed that. Yes, I like that suggestion. |
@jridgewell I don't remember suggesting having an error there. That one is yours (and I quite like it). |
That would explain why I missed it 😀 |
Ah, that makes sense. This stretches the edges of my spec knowledge, but is it possible to distinguish the arrow on the left vs. right side? e.g. this is valid: x |> x => x *2 |> x => x + 1 but this isn't x => x * 2 |> x => x + 1 |
Oh, that makes my head hurt. I believe we want it to parse as: x
|> x => x *2
|> x => x + 1 If we simplify it into is basest form: x
|> x => x
|> x => x We wan this to still be legal. But if we write it in shorthand form: x |> x => x |> x => x I can't tell where it supposed to parse. Maybe someone else can help? Or maybe it's just not possible. |
Yeah, we want it to parse as: x
|> x => x *2
|> x => x + 1 My question is more whether we can define the spec such that the unparen'd arrow is legal on the RHS but not the LHS, given how the pipeline is typically used. The shorthand "rule" for mentally parsing arrow functions, as per @pygy, is "the pipeline operator terminates an arrow body." |
@mAAdhaTTah You can't have that and |
What if we split the grammar into two phases? A
So:
We do something similar with Optional Chaining. |
Where are these grammar productions used (other than within themselves)? |
At the moment:
With my proposed changes:
Oh, this would also allow us to ban |
I think the F#-style pipeline operator naturally creates the following expectations:
To make that work, you could parameterize the outer expression grammar (similar to how it's parameterized on "in") along the lines of: (Leaving out async arrows and plenty of other things)
I think the question becomes: do we want to introduce an operator that creates expectations that conflict slightly with the language's existing operator precedence rules (in certain contexts)? Is it worth it? |
For what it’s worth, I still think it creates the opposite expectations and value the unambiguous nature of parenthesized arrow function operands. |
Wait, why do we want to ban |
Because it should be written as |
We spent a while debating different syntaxes for |
The usage of
so I actually don't know if getting community feedback thru the babel plugin is the best route here. |
Is this about Babel stability guarantees? Maybe another transpiler could be a better platform for development? I think we already have plenty of evidence on these bug threads that many people would be disappointed if they had to use parens; the no-parens effort seems like worth a shot to me, though it takes some work. |
Both babel stability guarantees as well as community expectations. I'm concerned about going out and saying "F# is like this, with parens here and here but not here", have people dislike it, and then have to go back and say "no, actually, now it's reversed with parens here, but not here and here." I think it'll muddy the signals from the community; we already had this problem when we were looking at 5 proposals, not knowing what the operator is. I think potentially ending up with multiple variants of F# proposal would be bad. Given that, I'd prefer to commit to one and stick with it, and I find myself hesitating to commit to unparen'd arrow functions, especially given the fact that we cannot eliminate requiring parens for assignment. I have a couple questions though:
Trying to get the "expectations" question posed by @zenparsing & @charmander. |
About community expectations of stability: I was hoping that whichever way we decide on this question, we could communicate clearly to this is a very early experiment, the community that the F# and smart proposals are two points on a big spectrum, and we will use the experiences from this stage to inform the design of the following proposal. We are still tweaking Stage 3 proposals, so we will definitely be open to tweaking these alternatives as they progress. |
@jridgewell Going out on a limb: If we can spec It would be thus: const a = x => x
|> x => x + 2
|> double
|> console.log
// parses as (with all the parens)
const a = x => (x
|> (x => x + 2)
|> double
|> console.log) Is this possible? |
🤷♂️. |
@michaelficarra Thoughts? This possible? If it is, I think that would most closely match expectations. That's essentially what the babel plugin did (before we landed babel/babel#7818 to bring it in line w/ current minimal). |
@jridgewell Re: #104 (comment) , I'm a bit confused about what problem this suggestion is trying to solve. Are you trying to find a grammar that will work somehow and correspond to the expectation that you have non-parenthized arrow functions? If that's the goal, do you think @mAAdhaTTah 's proposal at valtech-nyc#3 would work? If I understand correctly, this PR would have the semantics of consistently choosing the narrow parenthization. EDIT: Oh, I see, that other PR would require too many parentheses in a common assignment case. In that case, I wonder if @zenparsing 's grammar in #104 (comment) would meet these full goals in a somewhat simpler way. |
@littledan I think his proposal essentially matches what we have at valtech-nyc#3. The question is more whether we can extend it as mentioned in #104 (comment), as I think that's probably most closely aligned with how people expect it to work/ |
Closing this issue, as the proposal has advanced to stage 2 with Hack-style syntax. |
I've mentioned this a few times, but I would like to officially include this comment from @pygy as part of Proposal 1. We'll see if this is feasible as part of the babel plugin implementation, but if it is, would anyone be opposed? That would mean pipelines would require parens to write within an arrow function:
This would introduce a minor footgun, as this:
would parse like this:
Thoughts?
The text was updated successfully, but these errors were encountered: