-
Notifications
You must be signed in to change notification settings - Fork 111
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
Request for justifications and guidance on await in pipeline #86
Comments
Sure, let me give my own thinking here. Broadly, As an example, if I have a long chain of function applications mixed with console.log(filter(parse(await fetch(extractRemoteUrl(await readDB(makeQuery('some query')))))); then I would very much expect to be able to write something along the lines of 'some query'
|> makeQuery
|> readDB
|> await
|> extractRemoteUrl
|> fetch
|> await
|> parse
|> filter
|> console.log; since this is how I'd generally think about what I'm writing. Otherwise the pipeline proposal is effectively unusable in 'some query'
|> makeQuery
|> readDB
|> (_ => _.then(extractRemoteUrl))
|> (_ => _.then(fetch))
|> (_ => _.then(parse))
|> (_ => _.then(filter))
|> (_ => _.then(console.log)) or 'some query'
|> makeQuery
|> readDB
|> (_ => _.then(extractRemoteUrl))
|> (_ => _.then(fetch))
|> (_ => _.then(_ => (_ |> parse | filter | console.log))) or (await fetch(
getRemoteUrl(await ('some query'
|> makeQuery
|> readDB))
)
|> parse
|> filter
|> console.log or, indeed, any of several other broadly equivalent options, all of which feel like awkward ways of expressing the thing I actually want to express. I think the obvious way of writing that long chain of function calls as a pipeline - the only obvious way - is the version in which I To address your example,
would not work as currently specified: Moreover, even assuming a global I would object to the inclusion of any proposal which could not be used cleanly with |
👍
Higher order functions are cool, but definitely shouldn't be necessary to accomplish something so simple. Not to mention how difficult it'd be for a beginner to understand. I cannot imagine any beginner being able to think of this solution on their own.
|
Thank you for the input please keep it coming.
It doesn't need to be global, it can be an import, it can be a static function on Promise. The point is, we can solve this with functions today.
True, but if you're writing async heavy code, then you'll likely be interspersing
It appears including it is complicating an otherwise simple proposal. So even if you believe it needs to be supported, why can't we get a simple version into the language first, and add await afterwards? |
Yes. But it won't be on every step, just those which require
Because the ultimate method by which |
Just to reiterate, shipping a non awaiting supporting So for now: 'some query'
|> makeQuery
|> readDB
|> await
|> extractRemoteUrl
|> fetch
|> await
|> parse
|> filter
|> console.log; Is simply: import { then } from wherever
'some query'
|> makeQuery
|> then ( readDB )
|> then ( extractRemoteUrl )
|> then ( fetch )
|> then ( parse )
|> then ( filter )
|> then ( console.log ) I understand a little better why the committee wants it supported. And I'm not even opposed to it. I'm opposed to it complicating a simple proposal and delaying it potentially unnecessarily. I personally prefer the latter, and want to know I'm dealing with Promises. But I'm not all users, and that's fine. But can we get this into the language as is and solve this problem in a subsequent release? If not, why? |
That's a sign to me, that we're approaching this the wrong way. |
I think its debatable, and again designing for existing usage not for future usage. Of course it uses await, await is already in the language. |
Sure it does. Or rather, to be precise, it prevents us from shipping some possible designs. For example, to support the syntax I'm using above we might (or might not) want to ban This is the primary experience of designing JavaScript: our past decisions constrain our future ones. Shipping an incomplete design often prevents us from shipping the design we'd ultimately prefer.
It'll be years and years and years before you can use this feature on the web, assuming it even gets through committee; for the foreseeable future all use of this feature will be through Babel. But you can write your own Babel plugins, now, that do whatever you want! You don't need TC39 for that. I don't think this is a good argument for shipping a feature we have not entirely thought through, including its interactions with other parts of the language like
I also want to know I'm dealing with promises, but that's what using Moreover, the version without
So is You can't justify arbitrary designs by saying that they're designed for future usage. If you'd like to give a reason to believe that |
In the linked tc39 discussion it was proposed await could be banned to allow for a release. So you could ship now, and add support later.
I hear this argument a lot, but it’s impractical. I do not want to use a babel plugin for a feature that is unlikely to ever land because then I’ve got legacy code for a language that doesn’t exist. If a basic version is on a standards track, I am more likely to take the chance.
The behavior of Promises is orthogonal to your point, you can await non Promises, you can await
I do use
I’m justifying implementing a Yes, I do think our industry is trending towards functional practices, and I do think composition of pure functions is the best solution we have to problems like concurrency/distributed system. And I'm confident that ideas that were very recently considered fringe, our now mainstream, and that trend will continue. But even if you don't believe that, or see the relevance to this discussion - it doesn't matter, I'm proposing something proven should be shipped first. It's not an arbitrary design by any means. I'm looking for justifications for a constraint that is leading to designs like #84.
That’s not my aim at all. I’m not opposed to adding it. But I’ve just seen a proposal that takes the core proposition of composition and introduced new concepts based on a relatively new language to solve problems for users that haven’t requested them based on unproven needs. Such a proposal leads me to wonder, why are these constraints present in the first place? And if these constraints are forcing such radical changes to an already proven design, are the constraints justifiable? But I really don’t want you to think I’m against adding await. I just want to make sure it’s not going to make FP language features awkward to use without justification. Your await proposal seems fine to me. But #84 does not. And the justification for that proposal is supporting await, hence this thread. If we can add |
I'm in strong agreement with @JAForbes . I've been watching this proposal for several months. Over that time, it has seemed to me that discussions revolving around how (and whether) to force support for It would be a real shame if adding support for Removing a feature from a language is much harder than adding a new one. With that in mind, I am very strongly of the opinion that it makes sense to hold off on including support for |
Note that that argument is also one for not adding pipeline in the first place, until after figuring out the shape of await support. |
I would prefer no native pipeline operator to an overly complex operator that requires a tortured syntax and / or is difficult for runtime engines to optimize. I would gladly continue to use existing implementations of |
Only if we wanted to go with that one particular design, which, if we had already decided, we could just include in the proposal to start. That's not a general solution.
That's understandable, but your reluctance really does not seem like a sufficiently good reason to rush an incomplete feature through committee to me.
I don't think it is orthogonal. If I'm using
I disagree strongly with the idea that it is more radical to include
The core of my response continues to be what I gave in my first comment: because
I don't think I interpret this the same way you do. To me this says that there's a lot of demand for And I want to push back on the idea that
While true, this is not an argument for ignoring the problem. I think including support for
As Jordan says, the second sentence here does not at all follow from the first. Just the opposite, in fact. |
It's normal to feel disappointment and frustration when we feel like our point of view is being deprioritized. On the other hand, language design (especially for a lingua franca like Javascript) is a kind of public policy debate, where we must balance the points of view of all participants and strive for holistic, rather than pure, beauty. In that sense, it's much more productive to focus on the actual harm that a proposed policy might cause (e.g. burdensome repetition of a binding token) rather than on abstract notions about who "wins" and who "loses". |
@zenparsing I'm not interested in winning or losing at all. I hope that's being conveyed. I really just want this feature to be the best it can be. And I want it to be enjoyed by everybody. I think this feature will help me teach FP to a wider audience, it's a catalyst. I just want to be absolutely sure we're not sacrificing core functionality without being absolutely sure it's justified. But I'm not at all interested in winning.
It's not really incomplete or rushed if it's already used in many other languages. It's just a commitment that composing functions is what
Just to clarify, when I said radical I meant it in the dictionary sense. As in, it's a new untested idea. Not as in it's a reckless or bad idea. I think it would probably be a good fit providing composing functions isn't hindered.
I think that's less true the moment you have But if you write programs that lean on composition you rarely have variables, you want to avoid I program with That's not to say you can't mix the styles, that should be encouraged, but I don't want to sacrifice the style it does enable, for the benefit of a style it doesn't. We are adopting an existing feature, and that feature was designed with an explicit purpose, so I think it's reasonable to not sacrifice it's initial purpose when there's already affordances for other styles (like method chaining).
I think this is a good resource if this question comes up in the future. I don't agree with your justifications but I don't think they're unreasonable either. I'm just happy to have an answer. Thank you for everybody's time. I'm going to close this issue now, but please feel free continuing the discussion if there's more to say. |
Was it actually established that await support is required for this proposal to move forward? The TC39 discussion notes didn't indicate that the group thought it was a requirement. I know some people here in the issues consider await important, but I think we should establish that the TC39 body considers it a requirement before we give in to unbounded bikeshedding. I suggest that this issue be re-opened until someone can point to some kind of consensus that this feature request is actually blocking, or we determine that it is not blocking. @littledan you're the champion, have any thoughts? |
@TehShrike The conclusion was reached above; @bakkot is a member of the committee. |
I recognize/respect that, but one committee member's voice is not consensus. The discussion at the last meeting would seem to put him in the minority of committee members. |
Consensus typically means that every member must agree. |
Are you implying that if one TC39 member gives the thumbs-down to a proposal, it won't move forward? I don't know enough about TC39 policies in this area. I assumed that if a majority of members were against adding await, it would be appropriate to advance the feature without await. If a minority of members want await, and a majority don't want await, does that mean that the proposal can't move forward at all? Does it imply that the proposal must/must not include await to progress? |
Yes, that’s what consensus means - that any one member can block anything (although often, if only one member is dissenting, they may choose to withdraw their objection). So, if even one member thinks the proposal must include await to proceed, then it can never proceed while that is true and it lacks await. (To clarify, @bakkot is not the only member who thinks await is a requirement here in some form; i share his concerns.) |
I'm not familiar with TC39's inner workings, so I appreciate the explanation. From what you're saying, I assume that if there are committee members who think that await is too complex/undesirable, then the proposal can't proceed with the feature either? I'm most concerned about deadlock, I don't want to miss out on this language feature because no good compromise exists :-x Maybe it' would be useful to frame the discussion in the other issues as "is it possible to alter the proposal in a way that satisfies both groups (anti-complexity and pro-async-feature)." If not, I suppose the group will either settle for a complex pipeline operator, a pipeline operator without async, or the proposal will die in deadlock. |
Was the current pipeline proposal discussed at the most recent TC39 meeting, the 62nd in late January 2018? The 62nd’s agenda does not include an item for the proposal, and the 62nd’s notes have not yet been published in the usual repository for meeting notes. For reference, here is the relevant discussion from the 61st TC39 recent meeting in November 2017. The discussion was largely exploratory in nature, went over time with no conclusion, and was deferred to the overflow agenda. There isn’t any more recorded discussion for the 61st. For what it is worth, the 61st’s discussion occurred before parameterized pipelining was first proposed (by @gilbert in #75 and by @zenparsing in #84). Adding parameterized pipelining as an additional operator from the current proposal’s tacit pipelining—like how Clojure separates them into |
To be clear, this isn't something I'd block consensus for, but without wanting to speak for anyone else I would guess that much of the rest of the committee would similarly feel that interaction with the rest of the language, including |
No, it wasn't established in committee; earlier comments I made were based on out of committee discussion, and no one threatened to withhold consensus. However, we are still pretty early in the process. I think now is a good time to focus on gathering requirements. Await is frequently requested and makes logical sense here, so I'd like to support it unless there is a strong reason not to (e.g., if it were impossible without tons of complexity and problematic edge cases). |
@bakkot
I'd like to hear the reasoning for including await in the pipeline itself. I believe it's unnecessary, especially for an initial release and without a solid justification. We should seek to release a
|>
that only executes functions and leave ourselves room to add it if there's community demand for it in the wild.I do not want to give the impression that this is an OO/FP schism. I like
await
, but I do not see it's usage in the pipeline as intuitive or helpful, and it's inclusion as affecting core functionality of the proposal.I can easily see myself awaiting a pipeline
await x |> f |> then (g) |> then (h)
. I Think that's quite intuitive.And I can see myself awaiting within a function in a pipeline:
But both these examples fit in with the existing design of the language, it meets expectations, it's intuitive, simple and flexible.
If I'm wrong, we can always come back and add await when we are all clear what the best way to do that turns out to be. But I see no reason not to move a simple pipeline forward.
#84 proposes removing automatic function execution to accommodate the committee's request, but that makes the default usage awkward. And to propose such amendments simply to accommodate a need that I haven't heard a justification for, seems questionable.
The text was updated successfully, but these errors were encountered: