Skip to content
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

Why is this still stage 0? #35

Closed
calebmer opened this issue Jul 12, 2016 · 45 comments
Closed

Why is this still stage 0? #35

calebmer opened this issue Jul 12, 2016 · 45 comments

Comments

@calebmer
Copy link

I saw this proposal a while ago and almost every other week I find another situation where I’d want to use it. So why is it still stage 0?

As a note it seems like this proposal is important considering the new iterable additions to the language:

Array.from(iterable::map(x => x)::filter(x => x))

This way we could have lazy map/reduce evaluations.

@zenparsing
Copy link
Member

@calebmer For sure. Contact your favorite TC39 member and tell them to get on board with it! 😄

(I'm not currently doing TC39 work, so it can't be me.)

@calebmer
Copy link
Author

Unfortunately I haven’t been collecting my TC39 “baseball cards” if you will. Any recommendations? I could just ping every single TC39 member who’s name I recognize, but by the fact that I know there name means they might not be able to pick this up 😉

@calebmer
Copy link
Author

Also, what’s the correct terminology, am I looking for a “champion”?

@zenparsing
Copy link
Member

Right, "champion". You might be able to catch Pokemon, I mean TC39 members, by looking at participants listed in the meeting notes. My experience has been that several committee members are positive to the proposal, but none have stepped forward.

@calebmer
Copy link
Author

You have obviously worked with some of them before, do you have a name to suggest? 😊

@zenparsing
Copy link
Member

@littledan @domenic @bterlson @jeffmo

I keep getting pinged about why this proposal (bind-this double colon) is still at stage 0. Anyone from your organizations interested in taking it on?

@peet
Copy link

peet commented Jul 13, 2016

I took it that @ljharb was interested (or maybe just supportive in general), from his reaction to his mention on a comment in #24.

@zloirock
Copy link

Funny. So that mean all your other ES proposals like 'Observable', private fields or async iteration no longer official ES proposals (champions required for that)?

@zenparsing
Copy link
Member

@zloirock Oh, they're still official proposals, for sure, but they need a champion to advance. Async iteration still needs a champion I think, but the other two are covered.

@ljharb
Copy link
Member

ljharb commented Jul 13, 2016

@calebmer what "new iterable additions"? I've seen no proposal for that.

When my current plate of proposals gets a bit smaller, if this proposal is still unchampioned, I'll definitely try to scoop it up. At the moment, however, I don't have the resources.

@calebmer
Copy link
Author

@ljharb I meant something more like “new addition of iterables,” I think that the very existence of iterables and other abstract interfaces like thenables in the specification warrants a feature like this in the language to aid in consuming these interfaces across code boundaries.

@ljharb if you don’t currently have the resources, could you recommend someone who might?

@littledan
Copy link
Member

There are a couple different separable parts of this proposal: Infix :: for pipelining and prefix :: for function bind. I've heard that the latter is more useful. Even though I have a huge amount of sympathy for the first one, some people find it confusing because what follows the :: is looked up in the local lexical scope. I've met programmers who say the two things they use non-ES6 Babel features for are async/await (which is almost at Stage 4) and prefix ::.

If someone separated out the two meanings, and confirmed my intuition about the prefix case being the important one, then I think this would be a better proposal. Maybe this work could be done by someone from the community, and following that, a TC39 member could pick it up and champion it more easily (as TC39 members have done for other proposals). The hard part of the work is understanding and communicating the community needs.

I've heard part of the interest in this proposal is that it's thought that prefix :: would somehow be faster than Function.prototype.bind; for V8's part, we've been optimizing that function, so it might be better to leave performance out of this motivation.

The other thing to evaluate is if this is really want we want to use the :: token for (as opposed to, say, types). Once we use it for bind/pipelining, it'd be harder to also use it for something else. We don't have that many nice-looking tokens left in JS, so this is a big deal.

@deontologician
Copy link

Personally, I'm interested in this proposal for the infix notation (for use with rxjs and underscore style toolbox libraries). The prefix notation is kinda convenient, but rare enough use case that function.bind is fine

@domenic
Copy link
Member

domenic commented Jul 13, 2016

I tend to agree. I always thought the infix notation was the more interesting part, as evidenced by the plethora of es-discuss threads and proposals for different types of pipelining syntax. Prefix only feels like a nice potential bonus, but I'd rather just stick with Function.prototype.bind, if there's no infix version for it to be symmetrical with.

@ssube
Copy link

ssube commented Jul 13, 2016

While the bind shorthand is nice in event-heavy apps, I think the pipeline operator is far more useful in a lot more libraries.

@bergus
Copy link

bergus commented Jul 13, 2016

I believe both parts are equally important.
But is this double-feature really what is holding this proposal from advancing?

@bterlson
Copy link
Member

FWIW, this proposal is interesting to me for the infix notation. The prefix is a convenient sugar but not one I think is super critical.

The thing that has been giving me pause about championing this feature is I believe we probably don't want two syntaxes for pipelining things (one via this, ala this proposal) and another via first argument (eg. pipeline operator proposal) and I'm not sure how to combine them or which is more important/a better fit for JS long-term.

@Alxandr
Copy link

Alxandr commented Jul 13, 2016

I agree on the infix operator. Though, the reason it's important to me is the lack of a "better" way to do pipe-lining functions in JS (without prototype modifications). I'd much prefer something that sets first/last argument than the magical this, but this functionality in babel was the only thing that enabled me to write code the way I wanted to, which is why I'm for it. I (as well as others have) also made a library for dealing with all sorts of iterables using this syntax which allows for stuff like [1,2,3]::map(n => n * 2)::toArray(). Though my ultimate wish would be something more F# like:

[1, 2, 3]
|> Iter.map(n => n * 2)
|> Iter.toArray()

To me the :: operator is one of "I'll take it if I can get it", because it's much better than nothing.

@bergus
Copy link

bergus commented Jul 13, 2016

@bterlson

we probably don't want two syntaxes for pipelining things (one via this, ala this proposal) and another via first argument (eg. pipeline operator proposal) and I'm not sure […] which is more important/a better fit for JS long-term.

Well you'd have to decide whether you want JS to be more object-oriented or more functional :-)
There's been some discussion of this in tc39/proposal-pipeline-operator/issues/2, /issues/26 and /issues/19

I do however proclaim that first-argument-receivers are not functional at all. In properly curried languages, the data comes last, so that partially applying functions is easy and they cannot only be applied or pipelined, but also passed around. So if you want to go functional, you should aim for that.

Passing data as zeroth-argument (this) in contrast is just natural in OOP, and will allow for much simpler method borrowing.

@benjamingr
Copy link

I think there is consensus that infix :: is the more interesting one as it allows scoped binding of methods to objects.

@bergus
Copy link

bergus commented Jul 13, 2016

To appease the FP fraction, we could even devise a postfix :: operator that desugars

["abc"].some(String.prototype.includes::("b"))

to

["abc"].some(x => String.prototype.includes.call(x, "b")) // or
["abc"].some(((m, ...args) => x => m.call(x, ...args))(String.prototype.includes, "b")) // more precisely

thereby allowing OOP partial application :-) Uh, I'm bikeshedding again, definitely not suggesting to include that in the current proposal.

@Mouvedia
Copy link

Mouvedia commented Jul 13, 2016

I suppose the fact that your proposed :: operator conflicts with E4X and JScript doesn't help either.

@bterlson
Copy link
Member

@Mauvedia, I don't think it hurts :-P JScript will not be getting support for any new syntax, and it's so old by this point much code you run on the web every day doesn't work anyway.

@robotlolita
Copy link

Because JS is not Haskell (or OCaml, or ...), a pipeline operator that does not use the this argument to pass the data would be only really useful if the syntax described where the value should be passed, so:

a |> f(_, b) |> g(c, _)

Would be:

g(c, f(a, b))

Of course, _ can't be used to denote the hole in the application there, and I don't know any other available symbol that works reasonably well for this.

Which is why I'm more in favour of the this::fn operator than a value |> fn proposal.

@calebmer
Copy link
Author

@zenparsing, @littledan, @domenic, @bterlson, @jeffmo, @ljharb:

So that we have an actionable next step to getting the proposal a champion—I’ll separate out the infix part of this proposal with the prefix so we effectively have two proposals. Then we would need two champions. Can we agree this is the correct course of action and does anyone want to champion either of these proposals?

@littledan, you expressed interest in the prefix case, would you be willing to champion this half of the proposal?

@domenic, would you be interested in championing the infix half of this proposal?

@domenic
Copy link
Member

domenic commented Jul 14, 2016

Sorry, I don't have enough capacity to champion a proposal like this right now.

@littledan
Copy link
Member

I'm also not going to champion either of these proposals right now, sorry. There is a separate proposal for |> at https://github.com/mindeavor/es-pipeline-operator/ . @appsforartists mentioned to me that RxJS users make heavy use of this feature; @jhusain, would you be interested in looking into this further?

@calebmer
Copy link
Author

@jeffmo, @bterlson, @jhusain:

Do any of you have interest in championing this proposal or part of it? For a quick thread recap, this proposal allows two main things:

This bind prefix syntax:

emitter.on('event', ::this.handleEvent)

…which is equivalent to:

emitter.on('event', this.handleEvent.bind(this))

…and an infix syntax:

observable::map(() => {})

…which is equivalent to:

map.call(observable, () => {})

It seems like there is a lot of demand from the community for both of these features, and we’re looking for a champion for both “halves.” We could keep them in one proposal and have one champion, or we could split them out and have a champion for each.

@jhusain as I understand it the infix syntax is critical for the future of RxJS and ES7+, would you be interested or do you know anyone else who would be interested to champion this proposal?

@jhusain
Copy link

jhusain commented Jul 14, 2016

I don't think that this proposal is critical to Rx anymore than it is critical to the libraries like underscore or lodash. That said, it would certainly make FP patterns in JS a lot more ergonomic. My concern is the time commitment required to move an additional proposal through the committee. My recollection was that the latter half of this proposal was pretty controversial.

@jeffmo
Copy link
Member

jeffmo commented Jul 14, 2016

Yea, unfortunately the effort to move another proposal from start to finish at TC39 is just far more than I can afford to spend right now.

I do think this is an interesting proposal, though, and would love to see it ship in some form (even if only paired down to one of its two parts).

@calebmer
Copy link
Author

@jhusain agreed, but RxJS has taken it one step further by putting it in the docs and calling it the "best method possible." At this moment (without support) this proposal likely won't even move out of stage 0 for another 3–4 months and getting it into the standard could take a whole year. Considering I first heard the excitement for this more than 6 months ago it's a shame that it will take about 2 years for what many libraries consider to be a best practice to become a specced reality.

So considering Rx has a publiclly stated interest in the success of this proposal, could you make the time (or find someone who could make the time) to at least move this proposal forward? And if there's anything the community could do to make time less an issue, what would that be?

@appsforartists
Copy link

It sounds like the controversy is around the conflation of method binding (::console.log) and pipelining functions (observable::map()::filter()). Perhaps unbundling those concerns will help move the process forward.

There's a proposal for an independent pipeline operator (|>), but the person who wrote it doesn't have spec text, and may not be familiar enough with the TC39 process to write it on his own. Any TC39 members willing to help mentor @mindeavor through writing spec text?

@Igorbek
Copy link

Igorbek commented Jul 14, 2016

I'm wondering how that pipeline operator could ever be considered as an alternative to bind operator? It solves very different problem. The pipeline operator doesn't offer anything in this binding at all.

@zenparsing
Copy link
Member

@appsforartists We went through all of these concerns over a year ago. They are well-documented in the issues. We considered separating the proposals with different syntax, using first-arg, everything, and it turns out that none of those changes really amount to any real identifiable improvements to the feature (beyond OOP-vs-FP bikeshedding and cheerleading).

Of course, anyone that would like to go through the whole process again is more than welcome!

@Igorbek
Copy link

Igorbek commented Jul 14, 2016

@calebmer, I absolutely agree that it is very important for RxJS and other "pipelining" libraries. What we have now in RxJS with having to augment prototype is just a work around. I personally had worked a lot with RxJS typings and prototype approach prevented from better abstractions as we had in Rx.NET. (just a note)

@bergus
Copy link

bergus commented Jul 14, 2016

@appsforartists Don't forget that even the inline :: is still just a bind operator, although it can be used for pipelining: observable::map()::filter() desugars to filter.bind(map.bind(observable)())()

@appsforartists
Copy link

@bergus I know that. 😄

I've heard from a few sources that the conflation of the two use cases may have been causing friction, so I was just trying to unblock. Sounds like I'm out of my depth/not being helpful, so I'll retreat until I have anything more helpful to add.

@zenparsing
Copy link
Member

@appsforartists Apologies if I implied that you weren't being helpful, any ideas to unblock are worth exploring!

@ljharb
Copy link
Member

ljharb commented Jul 14, 2016

@bergus when followed by () it actually would desugar to .call, not .bind.

@domenic
Copy link
Member

domenic commented Jul 14, 2016

It could "desugar" to either. Neither desugaring is literally how it would work; either are appropriate approximations.

@Igorbek
Copy link

Igorbek commented Jul 14, 2016

Ok, so we haven't had any champion still? No more candidates?

@bterlson
Copy link
Member

@mattpodwysocki and I will champion this proposal.

@calebmer
Copy link
Author

@bterlson awesome 🎉

I'll close this issue now 🙌

@caub
Copy link

caub commented Oct 18, 2017

Array.from(iterable::map(x => x)::filter(x => x))
Array.from(iterable, x => x /*optional map arg*/).filter(x => x)

I don't see how the bind operator would make it better here

edit: oh right, processing less items in Array.from, or also plugging map to iterables

@MeirionHughes
Copy link

MeirionHughes commented Oct 18, 2017

@calebmer to have generic filter methods usable on other sources of data. i.e.

function* source(){ yield 1; yield 2; yield 3; }
function* filter(predicate){ 
  for(let item of this) 
    if (predicate(item)
      yield item;
}
for (let item of source()::filter(x => x > 1)){
  console.log(item);
}

This is really the huge selling point of the bind operator, because currently its painful to chain separate generators that work off other iterables. Really missing out on some awesome code without this bind operator, imho.

In your example, you're creating an array twice before you get to iterate the result, whereas with generators you map and filter each item one at a time. You can of course roll your own library (like linq ) to help with chaining stuff on iterables... or adulterate the prototypes of things.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests