Re: Scoped binding of a method to an object
Brendan Eich bren...@mozilla.com wrote: We already have good motivation for :: anyway, as sugar for bind. This gives relief to the OO side of the expression problem trade-off by allowing lexical bindings to be composed with method calls -- beautiful. No third scope axis / lookup parameter! Yeah, but this doesn't solve the original problem nearly as well IMO since it's suddenly different from a normal method call. Having a different call operator for scoped extension methods or method invocation seems very confusing and counter intuitive for developers. If I have to remember different invocation mechanics I kind of lost already and I don't have the polymorphism I wanted. I completely agree with Allen here. Allen Wirfs-Brock al...@wirfs-brock.com wrote: Now, what might be useful would be :: that has approximately this semantics ... ` _method ? _method : shuffle}.call(myArray);` What if the Array has the method further up the prototype chain - like on Object.prototype and we extend it on Array.prototype? Not to mention that the performance issues that plagued adding it to the normal invocation repeat here. On Mon, Oct 14, 2013 at 11:14 PM, Brendan Eich bren...@mozilla.com wrote: Right, that is a cost we always consider. Syntax can't be polyfilled. Once shipped at scale cross-browser, it ends to be forever. I've actually went around facebook groups with every day JavaScript developers yesterday. Probably mostly ones that don't know how to read the spec (even the really nice and clear ES5 one), but are working as full time JavaScript developers. Most of the people I talked to did not seem to appreciate having a breaking syntax change in order to have scoped extension methods. This is still very preliminary (~40 people) but I'd really like to get a stronger sense of what more every day developers think. I'll check around and I'll return with more significant data. You mean the use of 'this.constructor' to make generic Array methods that create array results in ES1-5 create appropriate subclass instances? Yeah, I think that's pretty cool - and I agree that if we can get away with it it's totally worth it :) On Mon, Oct 14, 2013 at 11:14 PM, Brendan Eich bren...@mozilla.com wrote: Definitely deep waters here, not one simple thing. Appreciate your interactions. Benjamin (Inglor) Gruenbaum wrote: But there were design issues too. ... user confusion or complexity remains an objection. Yes! This is the thing that bothers me /most/ right now about scoped extension methods. Introducing additional syntax to the language seems like a _huge_ objection to me, the fact that it's another thing to teach programmers and another thing to keep in mind when figuring out scopes when reading new code is a big deal in my opinion. Right, that is a cost we always consider. Syntax can't be polyfilled. Once shipped at scale cross-browser, it ends to be forever. Rick and Domenic pointed out to me that one of the bigger use cases I thought having scoped extension methods solves - extending a native object and not having to re-implement methods seems to be already solved by the clever way in the new spec and is under work. There are still interesting problems I think this solves but I'm really not convinced any more that adding the extra syntax is worth it. You mean the use of 'this.constructor' to make generic Array methods that create array results in ES1-5 create appropriate subclass instances? I still thought that was a breaking change on the web, which we were not sure we could get away with. But I agree with you it helps, a lot. Yet, it doesn't solve the use-cases at which the SOE strawman was aimed. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Generic Bundling
Le 14/10/2013 23:25, Brendan Eich a écrit : Jorge Chamorro wrote: The only work around for that is making as few requests as possible. +∞, +§, and beyond. This is deeply true, and a hot topic with browser/network-stack engineers right now. It ought to be with software engineers as well and it's one of the reason why promise pipelining [1] is so appealing. David [1] http://erights.org/elib/distrib/pipeline.html ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Generic Bundling
Le 14/10/2013 23:20, Jorge Chamorro a écrit : On 14/10/2013, at 22:11, David Bruant wrote: You already can with inlining, can't you? Yes and no: -It's much more complicated than pre zipping a bunch of files and adding a ref attribute. -It requires additional logic at the server side, and more programming. Not really. If there was a need for lots of people, people would have come up with an open source grunt task already (or any other open source tooling). The fact that people haven't tried too hard may also be an indication that bundling isn't such a pressing need. With the appropriate tooling, it could be as simple to inline in an HTML as it is to gzip (2 clicks for each). With tooling being such a hot topic these days (so many talks on tooling and automation in confs!) and the MIT-licence culture around it, I feel we, web devs, should start considering asking less from the platform and more from the tooling. -It's not trivial always: often you can't simply concatenate and expect it to work as-is (e.g. module scripts). -You might be forcing the server to build and/or gzip (á la PHP) on the fly = much more load per request. This is equally true from zip-bundling, no? -Inlined source isn't always semantically === non-inlined source = bugs. True. It's admittedly easy to escape with decent discipline. It would also be very interesting to know if you had .zip packing, would you be inlining? ... yeah ... good point, I probably wouldn't :-) David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
On 14 October 2013 22:10, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: But there were design issues too. ... user confusion or complexity remains an objection. Yes! This is the thing that bothers me most right now about scoped extension methods. Introducing additional syntax to the language seems like a _huge_ objection to me, the fact that it's another thing to teach programmers and another thing to keep in mind when figuring out scopes when reading new code is a big deal in my opinion. Arguably, the _syntactic_ complexity is not huge. It is almost benign, compared to the _semantic_ complexity. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
On Tue, Oct 15, 2013 at 12:50 PM, Andreas Rossberg rossb...@google.com wrote: Arguably, the _syntactic_ complexity is not huge. It is almost benign, compared to the _semantic_ complexity. Agreed. I have a bit of a problem articulating my thoughts clearly through this medium being new. The problem with introducing additional syntax to have scoped extension methods to the language is mostly the semantics scoped methods introduce by introducing the extra type of scope and not the extra rule in the language grammar. Even the syntax on its own sounds like a huge deal though, it's one more thing to teach every programmer learning the language JavaScript and an extra bit of cognitive overload. On Tue, Oct 15, 2013 at 12:50 PM, Andreas Rossberg rossb...@google.comwrote: On 14 October 2013 22:10, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: But there were design issues too. ... user confusion or complexity remains an objection. Yes! This is the thing that bothers me most right now about scoped extension methods. Introducing additional syntax to the language seems like a _huge_ objection to me, the fact that it's another thing to teach programmers and another thing to keep in mind when figuring out scopes when reading new code is a big deal in my opinion. Arguably, the _syntactic_ complexity is not huge. It is almost benign, compared to the _semantic_ complexity. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
On 15 October 2013 03:09, Allen Wirfs-Brock al...@wirfs-brock.com wrote: I still don't get why so many JS programmer with a FP orientation want to do things with the |this| binding. |this| is for us OO geeks, if you are doing FP you don't need it. Well, 'this' comes up because you cannot avoid having to interface with OOish APIs that conflicts with FPish composition patterns. For example, you'd like to be able to do something like array.map(String.prototype.toLowerCase) But map expects a function, while toLowerCase is only available as a method. So unless you rewrap all relevant APIs in functional style you have to deal with 'this' in one form or the other, and going back and forth is not pretty with what JS currently offers. (Mind you, a bind operator does not even address this particular example.) /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
On Tue, Oct 15, 2013 at 3:39 AM, Andreas Rossberg rossb...@google.comwrote: On 15 October 2013 03:09, Allen Wirfs-Brock al...@wirfs-brock.com wrote: I still don't get why so many JS programmer with a FP orientation want to do things with the |this| binding. |this| is for us OO geeks, if you are doing FP you don't need it. Well, 'this' comes up because you cannot avoid having to interface with OOish APIs that conflicts with FPish composition patterns. For example, you'd like to be able to do something like array.map(String.prototype.toLowerCase) Using http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming var bind = Function.prototype.bind; var uncurryThis = bind.bind(bind.call); array.map(uncurryThis(.toLowerCase)) But map expects a function, while toLowerCase is only available as a method. So unless you rewrap all relevant APIs in functional style you have to deal with 'this' in one form or the other, and going back and forth is not pretty with what JS currently offers. (Mind you, a bind operator does not even address this particular example.) /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
On Tue, Oct 15, 2013 at 3:45 AM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: Brendan Eich bren...@mozilla.com wrote: We already have good motivation for :: anyway, as sugar for bind. This gives relief to the OO side of the expression problem trade-off by allowing lexical bindings to be composed with method calls -- beautiful. No third scope axis / lookup parameter! Yeah, but this doesn't solve the original problem nearly as well IMO since it's suddenly different from a normal method call. Having a different call operator for scoped extension methods or method invocation seems very confusing and counter intuitive for developers. If I have to remember different invocation mechanics I kind of lost already and I don't have the polymorphism I wanted. I completely agree with Allen here. I don't think that the scoped extensions you want are going to happen. I used to like the idea of something like that, but I think it will cause a lot more confusion than its worth. My suggestion for the :: binding operator was basically just trying to leverage an operator that might be coming anyway and giving it more purpose. I mean, heck, you know JavaScript programmers, if :: got added to the language, you *know* people will use it to make nicer looking (subjectively) APIs in the way I'm describing. In regards to polymorphism - its not a polymorphic solution out of the box, or at least - it doesn't provide any affordances for doing polymorphism, but saying that function calls cannot be polymorphic isn't true, we're simply flipping around where the polymorphism happens. Yes, I know this probably sounds like a FP rant, but I think that you can't ignore the FP side of this (invoking the expression problem again here). OO is good at adding new cases to the datatype. Functional is good at adding new functions over the datatype (which is what we're doing here). Trying to get the best of both worlds likely means playing in the middle. I mean, this feels like a you got chocolate in my peanut butter you got peanut butter in may chocolate moment. You say, This operator makes my method calls unintuitive because its not a dot. Method calls should consistently use dots. I say, Variables (including function variables) already have well understood scoping and lookup behavior. The dot operator should have consistent lookup behavior. Is there a way to marry the functional and OO to solve this problem? If we didn't have :: (which we don't now), I think people will continue to simply use functions like what underscore does. Personally, I'm ok with that. If I want to have unscoped extensions and live with the consequences - I will be happy to use symbols. If I want to make a polyfill, I'll just do it the same way we've been doing it. But, as much as Allen seems to accuse me of being an FP guy, I still want to have a thing which feels like a method to be on the right so I find that using :: (if it existed) would be a nice compromise. Maybe I'll think about what clojure style protocols would look like to answer some of the polymorphism questions. - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
On Oct 15, 2013, at 6:40 AM, Mark S. Miller wrote: On Tue, Oct 15, 2013 at 3:39 AM, Andreas Rossberg rossb...@google.com wrote: On 15 October 2013 03:09, Allen Wirfs-Brock al...@wirfs-brock.com wrote: I still don't get why so many JS programmer with a FP orientation want to do things with the |this| binding. |this| is for us OO geeks, if you are doing FP you don't need it. Well, 'this' comes up because you cannot avoid having to interface with OOish APIs that conflicts with FPish composition patterns. For example, you'd like to be able to do something like array.map(String.prototype.toLowerCase) I'd be quite comfortable with saying: array.map(str=str.toLowerCase()) It preserves the integrity of of the string abstraction rather than just assuming that the naked String.prototype.toLowerCase function is the appropriate one for any particular str value. Using http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming var bind = Function.prototype.bind; var uncurryThis = bind.bind(bind.call); or, in a slightly less obscure formulation that ignores safety): let uncurryThis = f=((a0, ...args)=f.apply(a0, args)) array.map(uncurryThis(.toLowerCase)) although, I still content that array.map(str=str.toLowerCase()) is the better formulation. (and fewer characters for those who worry about such things) But map expects a function, while toLowerCase is only available as a method. So unless you rewrap all relevant APIs in functional style you have to deal with 'this' in one form or the other, and going back and forth is not pretty with what JS currently offers. (Mind you, a bind operator does not even address this particular example.) /Andreas I think arrow functions are the appropriate syntactic convenience and since this started as a discussion of the :: extension we can assume arrows already exist. We need to know and respect abstraction boundaries. I think careful thought is called for each time you cross the FP/OO boundary. You can't just assume that the a function you extracted from a method property is the right function to use with other objects. You can't just assume that the |this| value of a method corresponds to the first parameter of a function (or visa vera). Just because we know how an object is build out of functions, you shouldn't routinely take an object abstraction I've created and rip it apart into ins more primitive constituent elements which you then repurpose. To me, this is analogous to talking a function apart into its machine level code sequences and data structures and then doing clever things with them. It's possible, it might even be necessary in some very unusual situation, but it should never be routine. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
On Tue, Oct 15, 2013 at 8:51 AM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Oct 15, 2013, at 6:40 AM, Mark S. Miller wrote: On Tue, Oct 15, 2013 at 3:39 AM, Andreas Rossberg rossb...@google.comwrote: On 15 October 2013 03:09, Allen Wirfs-Brock al...@wirfs-brock.com wrote: I still don't get why so many JS programmer with a FP orientation want to do things with the |this| binding. |this| is for us OO geeks, if you are doing FP you don't need it. Well, 'this' comes up because you cannot avoid having to interface with OOish APIs that conflicts with FPish composition patterns. For example, you'd like to be able to do something like array.map(String.prototype.toLowerCase) I'd be quite comfortable with saying: array.map(str=str.toLowerCase()) It preserves the integrity of of the string abstraction rather than just assuming that the naked String.prototype.toLowerCase function is the appropriate one for any particular str value. Using http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming var bind = Function.prototype.bind; var uncurryThis = bind.bind(bind.call); or, in a slightly less obscure formulation that ignores safety): let uncurryThis = f=((a0, ...args)=f.apply(a0, args)) array.map(uncurryThis(.toLowerCase)) although, I still content that array.map(str=str.toLowerCase()) is the better formulation. (and fewer characters for those who worry about such things) It depends on what you're trying to express, as you pointed out earlier. Both address the FP vs OO mismatch -- your's by converting fp to oo, uncurryThis by converting oo to fp. Regarding Allen's question, I suspect your's is the better response ;). But map expects a function, while toLowerCase is only available as a method. So unless you rewrap all relevant APIs in functional style you have to deal with 'this' in one form or the other, and going back and forth is not pretty with what JS currently offers. (Mind you, a bind operator does not even address this particular example.) /Andreas I think arrow functions are the appropriate syntactic convenience and since this started as a discussion of the :: extension we can assume arrows already exist. We need to know and respect abstraction boundaries. I think careful thought is called for each time you cross the FP/OO boundary. You can't just assume that the a function you extracted from a method property is the right function to use with other objects. You can't just assume that the |this| value of a method corresponds to the first parameter of a function (or visa vera). Just because we know how an object is build out of functions, you shouldn't routinely take an object abstraction I've created and rip it apart into ins more primitive constituent elements which you then repurpose. To me, this is analogous to talking a function apart into its machine level code sequences and data structures and then doing clever things with them. It's possible, it might even be necessary in some very unusual situation, but it should never be routine. Allen -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
On Oct 15, 2013, at 7:22 AM, Russell Leggett wrote: If we didn't have :: (which we don't now), I think people will continue to simply use functions like what underscore does. Personally, I'm ok with that. If I want to have unscoped extensions and live with the consequences - I will be happy to use symbols. If I want to make a polyfill, I'll just do it the same way we've been doing it. But, as much as Allen seems to accuse me of being an FP guy, I still want to have a thing which feels like a method to be on the right so I find that using :: (if it existed) would be a nice compromise. Hey, it was a general rant and not specifically directed at you or anybody else. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
On Tue, Oct 15, 2013 at 11:59 AM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Oct 15, 2013, at 7:22 AM, Russell Leggett wrote: If we didn't have :: (which we don't now), I think people will continue to simply use functions like what underscore does. Personally, I'm ok with that. If I want to have unscoped extensions and live with the consequences - I will be happy to use symbols. If I want to make a polyfill, I'll just do it the same way we've been doing it. But, as much as Allen seems to accuse me of being an FP guy, I still want to have a thing which feels like a method to be on the right so I find that using :: (if it existed) would be a nice compromise. Hey, it was a general rant and not specifically directed at you or anybody else. Sure, no offense taken, I just don't put myself in that camp. Even the use of |this| I think is justified as not an FP abuse, I just haven't gotten a chance to flesh out my reasoning yet. Without elaborating too much, (sorry, no time right now), I basically envision the blend of clojure protocols and javascript as basically external mixins. Not just a single function, but potentially a set, and using the |this| for single dispatch the way clojure protocols use the first arg. - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
First of all interesting analogy and read. On Tue, Oct 15, 2013 at 5:22 PM, Russell Leggett russell.legg...@gmail.com wrote: I don't think that the scoped extensions you want are going to happen. I used to like the idea of something like that, but I think it will cause a lot more confusion than its worth. I'm not convinced either. What I'm going to do for the next couple of days is try to talk to developers about the original _problem_ and see if they even want to solve it. The confusion vs worth is something I'm trying to evaluate. Right now it looks like your estimation is correct but I'm not a fan of partial data. In a few days when I'll have more concrete data. I'll hopefully be smarter in this regard then. If we didn't have :: (which we don't now), I think people will continue to simply use functions like what underscore does. Personally, I'm ok with that I think using stuff like _.shuffle([1,2,3,4,5]) is not as nice and worse than [1,2,3,4,5].shuffle() . Especially in a more functional interface that does not return the original array (we can even have a generator here). Let's say I have an array [1,2,3,4,5], I want to filter the odd ones, double the remaining elements and then sum the result. (This is obviously not a real use case, but I think we both know there are such use cases) The big issue I see here is chaining. `_.reduce(_.map(_.filter([1,2,3,4,5],x=x%2 === 0),x=2*x),(x,y)=x+y)` Is a lot less readable than `[1,2,3,4,5].filter(x=x%2===0).map(x=2*x).reduce((x,y)=x+y))` The clever `.constructor` trick when extending `Array` solves _that_ use case but like Brendan said it doesn't address some of the ones in the old SOE proposal. Having another invocation syntax like `::` sounds like a __huge__ overhead to me. On Tue, Oct 15, 2013 at 5:22 PM, Russell Leggett russell.legg...@gmail.comwrote: On Tue, Oct 15, 2013 at 3:45 AM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: Brendan Eich bren...@mozilla.com wrote: We already have good motivation for :: anyway, as sugar for bind. This gives relief to the OO side of the expression problem trade-off by allowing lexical bindings to be composed with method calls -- beautiful. No third scope axis / lookup parameter! Yeah, but this doesn't solve the original problem nearly as well IMO since it's suddenly different from a normal method call. Having a different call operator for scoped extension methods or method invocation seems very confusing and counter intuitive for developers. If I have to remember different invocation mechanics I kind of lost already and I don't have the polymorphism I wanted. I completely agree with Allen here. I don't think that the scoped extensions you want are going to happen. I used to like the idea of something like that, but I think it will cause a lot more confusion than its worth. My suggestion for the :: binding operator was basically just trying to leverage an operator that might be coming anyway and giving it more purpose. I mean, heck, you know JavaScript programmers, if :: got added to the language, you *know* people will use it to make nicer looking (subjectively) APIs in the way I'm describing. In regards to polymorphism - its not a polymorphic solution out of the box, or at least - it doesn't provide any affordances for doing polymorphism, but saying that function calls cannot be polymorphic isn't true, we're simply flipping around where the polymorphism happens. Yes, I know this probably sounds like a FP rant, but I think that you can't ignore the FP side of this (invoking the expression problem again here). OO is good at adding new cases to the datatype. Functional is good at adding new functions over the datatype (which is what we're doing here). Trying to get the best of both worlds likely means playing in the middle. I mean, this feels like a you got chocolate in my peanut butter you got peanut butter in may chocolate moment. You say, This operator makes my method calls unintuitive because its not a dot. Method calls should consistently use dots. I say, Variables (including function variables) already have well understood scoping and lookup behavior. The dot operator should have consistent lookup behavior. Is there a way to marry the functional and OO to solve this problem? If we didn't have :: (which we don't now), I think people will continue to simply use functions like what underscore does. Personally, I'm ok with that. If I want to have unscoped extensions and live with the consequences - I will be happy to use symbols. If I want to make a polyfill, I'll just do it the same way we've been doing it. But, as much as Allen seems to accuse me of being an FP guy, I still want to have a thing which feels like a method to be on the right so I find that using :: (if it existed) would be a nice compromise. Maybe I'll think about what clojure style protocols would look like to answer some of the polymorphism questions. - Russ
Re: Scoped binding of a method to an object
If we didn't have :: (which we don't now), I think people will continue to simply use functions like what underscore does. Personally, I'm ok with that I think using stuff like _.shuffle([1,2,3,4,5]) is not as nice and worse than [1,2,3,4,5].shuffle() . Especially in a more functional interface that does not return the original array (we can even have a generator here). I prefer it too, which is why I suggested :: - its not as nice in terms of needing to understand a new operator, but it does allow you to think about it in a more OO way, and it allows for forward chaining without wrappers. Let's say I have an array [1,2,3,4,5], I want to filter the odd ones, double the remaining elements and then sum the result. (This is obviously not a real use case, but I think we both know there are such use cases) The big issue I see here is chaining. `_.reduce(_.map(_.filter([1,2,3,4,5],x=x%2 === 0),x=2*x),(x,y)=x+y)` Is a lot less readable than `[1,2,3,4,5].filter(x=x%2===0).map(x=2*x).reduce((x,y)=x+y))` Speaking of wrappers - underscore does have the chain method which wraps and allows for chaining. Not ideal, but better, and people are comfortable with it - I mean look at jQuery. Having another invocation syntax like `::` sounds like a __huge__ overhead to me. Its not an invocation syntax, its fairly trivial binding sugar which can be used to apply functions to objects as the receiver without modifying the object, which is precisely what you want to be able to do with SOE even if you don't like the syntax. - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
Benjamin (Inglor) Gruenbaum mailto:ing...@gmail.com October 15, 2013 12:45 AM Brendan Eich bren...@mozilla.com mailto:bren...@mozilla.com wrote: We already have good motivation for :: anyway, as sugar for bind. This gives relief to the OO side of the expression problem trade-off by allowing lexical bindings to be composed with method calls -- beautiful. No third scope axis / lookup parameter! Yeah, but this doesn't solve the original problem nearly as well IMO since it's suddenly different from a normal method call. Having a different call operator for scoped extension methods or method invocation seems very confusing and counter intuitive for developers. That's one-sided, though. The other side you are discounting is the confusion when code in the scope of the extension wants to call cowbow.draw not graphics.draw, but draw has been overridden on the right of dot. Any solution must allow programmers to say what they mean. Since new syntax is required even in the dot-based proposal (at the end, to declare the extension), the cost of an alternative to dot is not novel in the sense of breaking operation on downrev browsers. In other words, a compiler to older JS will be required in any event. If I have to remember different invocation mechanics I kind of lost already and I don't have the polymorphism I wanted. I completely agree with Allen here. Which polymorphism to people want? There is a DWIM aspect that cannot possibly cover all uses of, e.g., 'draw' on the right of dot. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
On Oct 15, 2013, at 9:44 AM, Benjamin (Inglor) Gruenbaum wrote: ... The big issue I see here is chaining. `_.reduce(_.map(_.filter([1,2,3,4,5],x=x%2 === 0),x=2*x),(x,y)=x+y)` Is a lot less readable than `[1,2,3,4,5].filter(x=x%2===0).map(x=2*x).reduce((x,y)=x+y))` first let me do a slight rewrite of the above to eliminate some semantic noise: import {reduce,map,filter} from underscore2; reduce(map(filter([1,2,3,4,5],x=x%2 === 0),x=2*x),(x,y)=x+y) vs [1,2,3,4,5].filter(x=x%2===0).map(x=2*x).reduce((x,y)=x+y)) Nobody should be thinking of these as equivalent expressions of the same computation. They aren't equivalent because the semantics of the identifiers reduce, map, filter are quite different in the two formulation. They mean different things and when express this way it is pretty clear that they are different. I don't see how making them look more similar (while maintaining the semantic difference) would help with code clarity. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
The big issue I see here is chaining. `_.reduce(_.map(_.filter([1,2,3,4,5],x=x%2 === 0),x=2*x),(x,y)=x+y)` Is a lot less readable than `[1,2,3,4,5].filter(x=x%2===0).map(x=2*x).reduce((x,y)=x+y))` P.S. This really doesn't look too shabby to me: import {reduce,map,filter} from underscore2; [1,2,3,4,5]::filter(x=x%2===0)::map(x=2*x)::reduce((x,y)=x+y)) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
Allen Wirfs-Brock mailto:al...@wirfs-brock.com October 14, 2013 6:09 PM Speaking from the perspective of someone whose probably has permanent OO brain damage, it doesn't do a lot for me. The reason I invoke a method on an object is because I want to do polymorphic dispatch on the method name. myArray::shuffle() doesn't do that for me. No polymorphic dispatch. If myArray actually does have a shuffle method it isn't called. If that sort of direct function invocation is what I want, I'll just code a function call. No method invocation syntax and no |this| value is need. Not so in the case of Russell's sketched underscore2 (note the 2). Underscore (http://underscorejs.org/) provides FP-style APIs hung off a _ object, e.g. _.map. Russell's myArray::shuffle() using a shuffle imported from underscore2 is clearly using an OO-style API from a made-up OO-style underscore2. I hope this is clear but fear it is not. I know it's not your main point -- that there's no fall-forward on Array.prototype.shuffle -- with which I agree. But it gets to why |this| matters. I still don't get why so many JS programmer with a FP orientation want to do things with the |this| binding. |this| is for us OO geeks, if you are doing FP you don't need it. If you want to write shuffle, each, and filter functions just code them as normal functions passing the collection as the first argument. That would be what underscore offers today, perhaps with better exports in an ES6 version (import {map, reduce} from underscore-mod, no need for _.map, just call map as a function). If I want to use you functions as a methods on one of my objects I'll just code something like: class { shuffle() {return shuffle(this)} } Why would you both writing such boilerplate if you did not have to? Assume that the problem of monkeypatching is solved somehow. Then two problems remain at play: P1. How to select an extension in a method (not function) call, in a large-ish extent of code where one may want to select a non-extension too (on any type of object). P2. How to fall forward when the extension is not needed because the built-in has the method. Now, what might be useful would be :: that has approximately this semantics import {shuffle,each,filter} from underscore2; myArray::shuffle(); desugars as do {let _method = myArray[shuffle.name]; _method ? _method : shuffle}.call(myArray); in other words, if myArray has a 'shuffle' method, call it; otherwise call the default shuffle method that I'm providing. SOE (http://wiki.ecmascript.org/doku.php?id=strawman:scoped_object_extensions) does this differently, by adding an extension object (associated with a prototype object) to a lexical scope, such that in that lexical scope, using an object that delegates to the extended prototype will use the extension, always. It will not fall forward to prefer a property from the object itself. Quoting from http://wiki.ecmascript.org/doku.php?id=strawman:scoped_object_extensions#property_lookup_spec_changes: Section 8.12.1 [[GetOwnProperty]](P) is modified as follows: When the [[GetOwnProperty]] internal method of O is called with property name P and lexical scope L, the following steps are taken: 1. Let D be the result of calling [[GetExtensionProperty]] on object O with property name P and lexical scope L. 2. If D is not undefined, return D. 3. Else return [[GetUnextendedOwnProperty]] on object O with property name P. When the [[GetExtensionProperty]] internal method of O is called with property name P and lexical scope L, the following steps are taken: 1. If O doesn’t have an object extension in lexical scope L return undefined. 2. Else let E be the object extension for O in lexical scope L. 3. Return [[GetUnextendedOwnProperty]] with object E and property name P. Ok, so maybe this lack of a (P2) solution is just an SOE design choice with which you disagree, but we need to be clear. Do we want fallback, or fall-forward, or neither? SOE was intended to provide an alternative to monkey-patching, with fallback when the named property is accessed on an unextended object. This is not the same as fall-forward, AKA object detection. Here I smell more DWIM. People do not mean the same thing when they write (just the expression) myArray.shuffle(). The meaning depends, as you say, at least on polymorphic dispatch via the prototype chain in JS today. We could add more potential kinds of meaning, but TC39ers rejected adding a semi-static or dynamic scoped lookup on right of dot, per SOE. What's left in my view is a combination of (a) monkey-patching as we know it (object detection is orthogonal and doable), or (b) some new operator that enables explicit here is what I mean; do it gesturing, or (c) the hypothetical, perhaps infeasible, static-only resolution system Andreas posed as a revived SOE requirement. It so happens that the bind operator -- a solution of the (b)
Re: Scoped binding of a method to an object
Russell Leggett wrote: The big issue I see here is chaining. `_.reduce(_.map(_.filter([1,2,3,4,5],x=x%2 === 0),x=2*x),(x,y)=x+y)` Is a lot less readable than `[1,2,3,4,5].filter(x=x%2===0).map(x=2*x).reduce((x,y)=x+y))` P.S. This really doesn't look too shabby to me: import {reduce,map,filter} from underscore2; [1,2,3,4,5]::filter(x=x%2===0)::map(x=2*x)::reduce((x,y)=x+y)) Right, I think :: beats _. any day :-P. Seriously, using underscore.js's _. is kind of sandbagging. Allen's right, FP-style looks fine but composes inside out rather than via chaining (FP'ers like this). No need for this or dot, if you can make the world (including built-ins) have this style of API. Using your proposed underscore2 (OO-underscore?) with :: is no more verbose than underscore.js (underscore1), and it has the chaining not inside-out-composing win some may prefer. We should not argue only about taste, and bind (::) has a champion and good rationale as an addition to the language. What I think we should argue about is whether SOE that solves either or both problems (P1 and P2) I identified is even possible. Andreas's static-only resolution requirement is good. Anyone want to work on that angle? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
Using your proposed underscore2 (OO-underscore?) with :: is no more verbose than underscore.js (underscore1), and it has the chaining not inside-out-composing win some may prefer. I'm glad you noticed the 2. Perhaps oonderscore? :) We should not argue only about taste, and bind (::) has a champion and good rationale as an addition to the language. What I think we should argue about is whether SOE that solves either or both problems (P1 and P2) I identified is even possible. Andreas's static-only resolution requirement is good. Anyone want to work on that angle? If we do assume static-only resolution, isn't that trivial to show its impossible? Wouldn't it require complete type inference? And even then, what about expressions that evaluate to more than one type? Btw, another thing I noticed, thinking about using the binding operator this way, is that it's also a perfect fit for array-likes and array methods. import {hide} from jQuoory; let {filter, forEach} = Array.prototype; document.getElementsByClassName('hello') ::filter(e = e.tagName === span) ::forEach(e = e::hide()); - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
Wait, I think maybe I did not understand what you meant before. Are we talking about using `::` for infixing the first parameter of the function? As in `func(a,b,c)` being the same as `a::func(b,c)` ? Would that let us do `[1,2,3,4,5]::_.reduce(x=x%2 === 0)::_.map(x=2*x)::._.reduce(x,y) = x+y))`? That could actually be pretty nice, and if that lets us do extension methods that could also be pretty interesting. Is this what you meant by `::` and then having extension methods as an extra syntax? If not, can you elaborate on `::`? If yes, I'm all ears. This sounds like an interesting syntactic sugar that could help. It doesn't solve the problem of putting the method where it belongs but it does solve chaining quite nicely. On Tue, Oct 15, 2013 at 7:58 PM, Russell Leggett russell.legg...@gmail.comwrote: If we didn't have :: (which we don't now), I think people will continue to simply use functions like what underscore does. Personally, I'm ok with that I think using stuff like _.shuffle([1,2,3,4,5]) is not as nice and worse than [1,2,3,4,5].shuffle() . Especially in a more functional interface that does not return the original array (we can even have a generator here). I prefer it too, which is why I suggested :: - its not as nice in terms of needing to understand a new operator, but it does allow you to think about it in a more OO way, and it allows for forward chaining without wrappers. Let's say I have an array [1,2,3,4,5], I want to filter the odd ones, double the remaining elements and then sum the result. (This is obviously not a real use case, but I think we both know there are such use cases) The big issue I see here is chaining. `_.reduce(_.map(_.filter([1,2,3,4,5],x=x%2 === 0),x=2*x),(x,y)=x+y)` Is a lot less readable than `[1,2,3,4,5].filter(x=x%2===0).map(x=2*x).reduce((x,y)=x+y))` Speaking of wrappers - underscore does have the chain method which wraps and allows for chaining. Not ideal, but better, and people are comfortable with it - I mean look at jQuery. Having another invocation syntax like `::` sounds like a __huge__ overhead to me. Its not an invocation syntax, its fairly trivial binding sugar which can be used to apply functions to objects as the receiver without modifying the object, which is precisely what you want to be able to do with SOE even if you don't like the syntax. - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
On Tue, Oct 15, 2013 at 4:28 PM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: Wait, I think maybe I did not understand what you meant before. Are we talking about using `::` for infixing the first parameter of the function? As in `func(a,b,c)` being the same as `a::func(b,c)` ? Not exactly. See the proposal http://wiki.ecmascript.org/doku.php?id=strawman:bind_operator Essentially, e1::e2 is equivalent to do { let obj=e1; e2.bind(obj) } Or, in the case of an immediate call, it skips the bind and just does a Function.prototype.call. In other words, obj::fun(a,b) is not the same as fun(obj,a,b). Its fun.call(obj,a,b). The important distinction is that the function being called is expecting a |this| as opposed to an extra first argument. This is reason I called it underscore2 - Brendan picked up on that calling it OO underscore. Functional purists can argue with the approach, but it would let you write functions exactly as though they were extension methods - using |this| where appropriate. The following is a somewhat silly example based on the SOE proposal module Collections { export { where: Array.prototype.filter, select: Array.prototype.map } } module LolCatzDotCom { // imports Array.prototype extensions where and select into this module import {where,select} from Collections; var allCatz = someArrayValue; // Array extensions are in scope var cuteCatNames = allCatz::where(cat = cat.isCute)::select(cat = cat.name); } If you still don't get it, give me an example, and I can probably show the :: equivalent. What is your ideal SOE form? Because my guess is that I can get it darn close with :: - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
I think I misunderstood `::` before. if `a::b(x_1,...,x_n)` _just_ means `b(a,x_1,...,x_n)` I think it might be a good solution to the chaining problem. I think the `.constructor` proposal as well as being able to do `::` completely eliminates the need for extension methods in this regard. It also behaves similarly to extension methods in C# in that it's _just_ a static method and it could also introduce interesting options. I'm not convinced about `::` yet but it seemed to get a lot more positive feedback from community members I really value and bloggers I talked to since. The (small) research I'm doing about scoped extension methods or the problem does not seem to get nearly as good of a response. The only issue here is: Which polymorphism to people want? There is a DWIM aspect that cannot possibly cover all uses of, e.g., 'draw' on the right of dot. Let's say I have a classic prototypical inheritance use case. Cat.prototype.meow = function(){... Kitten.prototype = new Cat() Kitten.prototype.purr = function(){ Now I have a catOrKitten object. If I define a `function purr(catOrKitten)` and call `carOrKitten::purr()` , regardless of it being a cat or a kitten - that function gets called. If I had an extension method on Cat.prototype, I'd get the correct behavior for kitten who overrides that method on its prototype. On Tue, Oct 15, 2013 at 8:26 PM, Brendan Eich bren...@mozilla.com wrote: Benjamin (Inglor) Gruenbaum mailto:ing...@gmail.com October 15, 2013 12:45 AM Brendan Eich bren...@mozilla.com mailto:bren...@mozilla.com wrote: We already have good motivation for :: anyway, as sugar for bind. This gives relief to the OO side of the expression problem trade-off by allowing lexical bindings to be composed with method calls -- beautiful. No third scope axis / lookup parameter! Yeah, but this doesn't solve the original problem nearly as well IMO since it's suddenly different from a normal method call. Having a different call operator for scoped extension methods or method invocation seems very confusing and counter intuitive for developers. That's one-sided, though. The other side you are discounting is the confusion when code in the scope of the extension wants to call cowbow.draw not graphics.draw, but draw has been overridden on the right of dot. Any solution must allow programmers to say what they mean. Since new syntax is required even in the dot-based proposal (at the end, to declare the extension), the cost of an alternative to dot is not novel in the sense of breaking operation on downrev browsers. In other words, a compiler to older JS will be required in any event. If I have to remember different invocation mechanics I kind of lost already and I don't have the polymorphism I wanted. I completely agree with Allen here. Which polymorphism to people want? There is a DWIM aspect that cannot possibly cover all uses of, e.g., 'draw' on the right of dot. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Readdition of __proto__
On Mon, Oct 14, 2013 at 8:32 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Oct 14, 2013, at 4:21 PM, Andrea Giammarchi wrote: my last memories on the topic are these: ```javascript var obj = JSON.parse('{__proto__:[]}'); obj instanceof Array; // false obj.__proto__ instanceof Array; // true // since the proto is a property, not a magic thing obj.__proto__ = 123; // da hell will happen, only Allen knows ^_^ ``` And since latter should simply set the property named `__proto__` as value `123` I got confused with this dual way to deal with an object when it comes from JSON world (then has a property defined as value, not the inherited set/get from Object.prototype) As summary, `JSON.parse` over `__proto__` is similar to: ```javascript var o = {}; Object.defineProperty(o, '__proto__', { value: 123, enumerable: true, writable: true, configurable: true }); ``` Which means in such case the property `__proto__` will fail with such object while `Object.setPrototypeOf` won't which is the reason I keep suggesting the latest to make the intent explicit. Not arguing or anything, just speaking out loudly my confusion with that property as string part. I think you are over thinking this: Assuming that Annex B.2.2.1 and B.3.1 are implemented: here are the cases of interest: let o1 = {__proto__: p}; // o1 inherits from p let o2 = {__proto__: p}; // o2 inherits from p let o3 = {[__proto__]: p};// o3 inherits from Object.prototype, has own data property __proto__ whose value is p. let o4 = JSON.parse('{__proto__: value}'); //o4 inherits from Object.prototype, has own data property __proto__ whose value is value //assuming that Object.prototype.__proto__ has not been tamper with: let o5 = new Object; o5.__proto__ = p ; //o5 inherits from p let o6 =new Object; o6[__proto__] = p; //o6 inherits from p There seems to be an interesting case missing: let attr = __proto__; let o7 = new Object; o7[attr] = p; // is this like o3? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
Thanks, this clarifies things (the difference between having `this` and a first argument is really not that big here at all imo and converting between them two is easy). What is your ideal SOE form? Because my guess is that I can get it darn close with :: It does seem a lot simpler than actual extension methods with scope resolution, my only problem with it is the polymorphic case (the equally silly Cat/Kitten case in my email to Brendan). I'll ask around and have better conclusions but it does seem to have better feedback from developers, I think use cases like chaining are good for the wiki page. On Wed, Oct 16, 2013 at 12:00 AM, Russell Leggett russell.legg...@gmail.com wrote: On Tue, Oct 15, 2013 at 4:28 PM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: Wait, I think maybe I did not understand what you meant before. Are we talking about using `::` for infixing the first parameter of the function? As in `func(a,b,c)` being the same as `a::func(b,c)` ? Not exactly. See the proposal http://wiki.ecmascript.org/doku.php?id=strawman:bind_operator Essentially, e1::e2 is equivalent to do { let obj=e1; e2.bind(obj) } Or, in the case of an immediate call, it skips the bind and just does a Function.prototype.call. In other words, obj::fun(a,b) is not the same as fun(obj,a,b). Its fun.call(obj,a,b). The important distinction is that the function being called is expecting a |this| as opposed to an extra first argument. This is reason I called it underscore2 - Brendan picked up on that calling it OO underscore. Functional purists can argue with the approach, but it would let you write functions exactly as though they were extension methods - using |this| where appropriate. The following is a somewhat silly example based on the SOE proposal module Collections { export { where: Array.prototype.filter, select: Array.prototype.map } } module LolCatzDotCom { // imports Array.prototype extensions where and select into this module import {where,select} from Collections; var allCatz = someArrayValue; // Array extensions are in scope var cuteCatNames = allCatz::where(cat = cat.isCute)::select(cat = cat.name); } If you still don't get it, give me an example, and I can probably show the :: equivalent. What is your ideal SOE form? Because my guess is that I can get it darn close with :: - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Readdition of __proto__
Not resolving this like o3 (or o6 really) sounds very strange. I think: let attr = __proto__; let o7 = new Object; o7[attr] = p; // o7 inherits from p Is the correct behavior here (why would it not invoke the setter?) On Wed, Oct 16, 2013 at 12:04 AM, Dean Landolt d...@deanlandolt.com wrote: On Mon, Oct 14, 2013 at 8:32 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Oct 14, 2013, at 4:21 PM, Andrea Giammarchi wrote: my last memories on the topic are these: ```javascript var obj = JSON.parse('{__proto__:[]}'); obj instanceof Array; // false obj.__proto__ instanceof Array; // true // since the proto is a property, not a magic thing obj.__proto__ = 123; // da hell will happen, only Allen knows ^_^ ``` And since latter should simply set the property named `__proto__` as value `123` I got confused with this dual way to deal with an object when it comes from JSON world (then has a property defined as value, not the inherited set/get from Object.prototype) As summary, `JSON.parse` over `__proto__` is similar to: ```javascript var o = {}; Object.defineProperty(o, '__proto__', { value: 123, enumerable: true, writable: true, configurable: true }); ``` Which means in such case the property `__proto__` will fail with such object while `Object.setPrototypeOf` won't which is the reason I keep suggesting the latest to make the intent explicit. Not arguing or anything, just speaking out loudly my confusion with that property as string part. I think you are over thinking this: Assuming that Annex B.2.2.1 and B.3.1 are implemented: here are the cases of interest: let o1 = {__proto__: p}; // o1 inherits from p let o2 = {__proto__: p}; // o2 inherits from p let o3 = {[__proto__]: p};// o3 inherits from Object.prototype, has own data property __proto__ whose value is p. let o4 = JSON.parse('{__proto__: value}'); //o4 inherits from Object.prototype, has own data property __proto__ whose value is value //assuming that Object.prototype.__proto__ has not been tamper with: let o5 = new Object; o5.__proto__ = p ; //o5 inherits from p let o6 =new Object; o6[__proto__] = p; //o6 inherits from p There seems to be an interesting case missing: let attr = __proto__; let o7 = new Object; o7[attr] = p; // is this like o3? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Readdition of __proto__
On Oct 15, 2013, at 2:10 PM, Benjamin (Inglor) Gruenbaum wrote: Not resolving this like o3 (or o6 really) sounds very strange. I think: let attr = __proto__; let o7 = new Object; o7[attr] = p; // o7 inherits from p Is the correct behavior here (why would it not invoke the setter?) This case is exactly the same as O6. Perhaps I should have written O6 as: o6[ (__proto__) ] = p; //o6 inherits from p to make that clearer. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Readdition of __proto__
Benjamin (Inglor) Gruenbaum wrote: Not resolving this like o3 (or o6 really) sounds very strange. I think: let attr = __proto__; let o7 = new Object; o7[attr] = p; // o7 inherits from p Is the correct behavior here (why would it not invoke the setter?) Allen confirmed, but just to be clear, any world where o[foo] and do { let key = foo; o[key]; } (do-expression syntax from harmony-era strawman) differ is crazytown, and we do not go there. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
Benjamin (Inglor) Gruenbaum mailto:ing...@gmail.com October 15, 2013 2:00 PM I think I misunderstood `::` before. if `a::b(x_1,...,x_n)` _just_ means `b(a,x_1,...,x_n)` No, rather: `b.call(a, x_1, ..., x_n)` but with the original Function.prototype.call (not any shadowing b.call). I think it might be a good solution to the chaining problem. I think the `.constructor` proposal as well as being able to do `::` completely eliminates the need for extension methods in this regard. It also behaves similarly to extension methods in C# in that it's _just_ a static method and it could also introduce interesting options. Indeed static methods with |this| uncurried are easier to call in the absence of ::, and this is why I added these so-called static generics to SpiderMonkey: js a = [1,2,3] [1, 2, 3] js Array.map(a, x = x*x) [1, 4, 9] js Array.reduce(a, (r,x) = r*x) 6 js // etc. Doing [].map.call(arraylike, mapfun) or worse, Array.prototype.map.call(arraylike, mapfun) is just no fun! The only issue here is: Which polymorphism to people want? There is a DWIM aspect that cannot possibly cover all uses of, e.g., 'draw' on the right of dot. Let's say I have a classic prototypical inheritance use case. Cat.prototype.meow = function(){... Kitten.prototype = new Cat() Kitten.prototype.purr = function(){ Now I have a catOrKitten object. If I define a `function purr(catOrKitten)` and call `carOrKitten::purr()` This is based on your misunderstanding corrected above -- :: binds the object to the left of :: to |this|, not to the first argument. regardless of it being a cat or a kitten - that function gets called. If I had an extension method on Cat.prototype, I'd get the correct behavior for kitten who overrides that method on its prototype. I don't see purr on Cat.prototype --what am I missing? Anyway, as Russell proposed, :: with imported *methods* (not |this|-free functions) is does call the named function, so without multimethods or any kind of dispatch based on arguments not receiver (this), you're right. You bind a method value to a name and call it on a given |this|. Allen objected that this doesn't do receiver-based dispatch, which I think was your point with the cat and kitten. That's true, and SOE has that advantage -- kind of. SOE as I understand the strawman looks in the extension object first, and the extension object has no protototype object. It's flat. If you use an extension name on some other object that is not extended, of course you get polymorphic receiver-based dispatch. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Readdition of __proto__
On Tue, Oct 15, 2013 at 5:50 PM, Brendan Eich bren...@mozilla.com wrote: Benjamin (Inglor) Gruenbaum wrote: Not resolving this like o3 (or o6 really) sounds very strange. I think: let attr = __proto__; let o7 = new Object; o7[attr] = p; // o7 inherits from p Is the correct behavior here (why would it not invoke the setter?) Allen confirmed, but just to be clear, any world where o[foo] and do { let key = foo; o[key]; } (do-expression syntax from harmony-era strawman) differ is crazytown, and we do not go there. True, but the __proto__ train left the station bound for crazytown long ago... So just to be clear, the only way to add a __proto__ property to an existing object is with Object.defineProperty? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Readdition of __proto__
On Oct 15, 2013, at 3:19 PM, Dean Landolt wrote: So just to be clear, the only way to add a __proto__ property to an existing object is with Object.defineProperty? Object.mixin(obj, {[__proto__]:42}); Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Readdition of __proto__
not if you parsed that object via `JSON.parse('{__proto__:[]}')` in this case is the equivalent of that operation through `Object.defineProperty({}, '__proto__', {enumerable: true, writable: true, configurable: true})` so that `obj.__proto__` will result into property assignment and no setter invoked. ```javascript var o = JSON.parse('{__proto__:[]}'); o.__proto__ = Date.prototype; o instanceof Date;// false o.getTime === void 0; // true delete o.__proto__; // true // once again o.__proto__ = Date.prototype; // but this time ... o instanceof Date;// true o.getTime;// function[native] ``` Cheers On Tue, Oct 15, 2013 at 3:19 PM, Dean Landolt d...@deanlandolt.com wrote: On Tue, Oct 15, 2013 at 5:50 PM, Brendan Eich bren...@mozilla.com wrote: Benjamin (Inglor) Gruenbaum wrote: Not resolving this like o3 (or o6 really) sounds very strange. I think: let attr = __proto__; let o7 = new Object; o7[attr] = p; // o7 inherits from p Is the correct behavior here (why would it not invoke the setter?) Allen confirmed, but just to be clear, any world where o[foo] and do { let key = foo; o[key]; } (do-expression syntax from harmony-era strawman) differ is crazytown, and we do not go there. True, but the __proto__ train left the station bound for crazytown long ago... So just to be clear, the only way to add a __proto__ property to an existing object is with Object.defineProperty? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Readdition of __proto__
oh, that's cute :D too bad I cannot shim/polyfill that in my `Object.mixin` module. I would simply *red-flag* it and discourage the usage of `__proto__` everywhere is possible (uhm wait ... I've already done that in the past, never mind ... ) Happy `__dunder__` Everybody, Cheers On Tue, Oct 15, 2013 at 4:03 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Oct 15, 2013, at 3:19 PM, Dean Landolt wrote: So just to be clear, the only way to add a __proto__ property to an existing object is with Object.defineProperty? Object.mixin(obj, {[__proto__]:42}); Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
wait ... what ? On Tue, Oct 15, 2013 at 2:00 PM, Russell Leggett russell.legg...@gmail.comwrote: obj::fun(a,b) is not the same as fun(obj,a,b). Its fun.call(obj,a,b). isn't this basically the equivalent of obj-fun then ? (yes, the other arrow that was an arrow too far) Thanks for clarification ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
uhm, never mind, I got it now. Borrowing functions avoiding call/apply looks good. Best Regards On Tue, Oct 15, 2013 at 4:17 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: wait ... what ? On Tue, Oct 15, 2013 at 2:00 PM, Russell Leggett russell.legg...@gmail.com wrote: obj::fun(a,b) is not the same as fun(obj,a,b). Its fun.call(obj,a,b). isn't this basically the equivalent of obj-fun then ? (yes, the other arrow that was an arrow too far) Thanks for clarification ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
On Wed, Oct 16, 2013 at 1:04 AM, Brendan Eich bren...@mozilla.com wrote: No, rather: `b.call(a, x_1, ..., x_n)` but with the original Function.prototype.call (not any shadowing b.call). Right, Russell clarified `::` to me and sent a link to the wiki (always good!). Thanks. I don't see purr on Cat.prototype --what am I missing? You're missing nothing. Cat doesn't have a `purr` on the prototype but Kitten whose prototype is a cat does. By adding a scoped extension to Cat.protoype to the current module and then calling `myObj.purr` I'd expect: - If myObj is a Cat, the scoped extension will be called - If myObj is also a Kitten, Kitten.prototype.purr will be called instead since Kitten.prototype is sooner in the prototype chain. This enables a sort of polymorphism in my opininion - whether it's very useful or not is another question but it's something the `::` bind syntax doesn't really solve. Allen objected that this doesn't do receiver-based dispatch, which I think was your point with the cat and kitten. That's true, Yes, that's the issue - but I'm no longer as convinced that the use case is strong enough to justify a whole new language construct. On Wed, Oct 16, 2013 at 1:04 AM, Brendan Eich bren...@mozilla.com wrote: Benjamin (Inglor) Gruenbaum mailto:ing...@gmail.com October 15, 2013 2:00 PM I think I misunderstood `::` before. if `a::b(x_1,...,x_n)` _just_ means `b(a,x_1,...,x_n)` No, rather: `b.call(a, x_1, ..., x_n)` but with the original Function.prototype.call (not any shadowing b.call). I think it might be a good solution to the chaining problem. I think the `.constructor` proposal as well as being able to do `::` completely eliminates the need for extension methods in this regard. It also behaves similarly to extension methods in C# in that it's _just_ a static method and it could also introduce interesting options. Indeed static methods with |this| uncurried are easier to call in the absence of ::, and this is why I added these so-called static generics to SpiderMonkey: js a = [1,2,3] [1, 2, 3] js Array.map(a, x = x*x) [1, 4, 9] js Array.reduce(a, (r,x) = r*x) 6 js // etc. Doing [].map.call(arraylike, mapfun) or worse, Array.prototype.map.call(**arraylike, mapfun) is just no fun! The only issue here is: Which polymorphism to people want? There is a DWIM aspect that cannot possibly cover all uses of, e.g., 'draw' on the right of dot. Let's say I have a classic prototypical inheritance use case. Cat.prototype.meow = function(){... Kitten.prototype = new Cat() Kitten.prototype.purr = function(){ Now I have a catOrKitten object. If I define a `function purr(catOrKitten)` and call `carOrKitten::purr()` This is based on your misunderstanding corrected above -- :: binds the object to the left of :: to |this|, not to the first argument. regardless of it being a cat or a kitten - that function gets called. If I had an extension method on Cat.prototype, I'd get the correct behavior for kitten who overrides that method on its prototype. I don't see purr on Cat.prototype --what am I missing? Anyway, as Russell proposed, :: with imported *methods* (not |this|-free functions) is does call the named function, so without multimethods or any kind of dispatch based on arguments not receiver (this), you're right. You bind a method value to a name and call it on a given |this|. Allen objected that this doesn't do receiver-based dispatch, which I think was your point with the cat and kitten. That's true, and SOE has that advantage -- kind of. SOE as I understand the strawman looks in the extension object first, and the extension object has no protototype object. It's flat. If you use an extension name on some other object that is not extended, of course you get polymorphic receiver-based dispatch. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss