Re: Final ES6 Draft (Jason Orendorff)
Awesome work! Truly an exciting milestone. A lot of really nice stuff is in, and the future with ES7 looks bright. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: How to fix the `class` keyword
Not sure why this is a reply to me - but I completely agree. All `class` does is take an extremely common idiom and makes it simpler and easier to get right with better defaults - it _is_ the same prototypical stuff. It's an addition based on what people do and it's still entirely possible to do it any other ES5 way. On Wed, Mar 4, 2015 at 6:00 PM, joe joe...@gmail.com wrote: As someone who has fifty or sixty thousand lines of code using the new class syntax, I find this hard to understand. When I run into cases that aren't suited for the new class syntax, the solution is easy: *I don't use it*. If one tool isn't fit for the job, pick up another! After all, no one is proposing we *remove* the old prototypal stuff. The class syntax solves one set of problems. The more flexible prototypal stuff solves another, and from my own experience they work pretty well together. Joe ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: How to fix the `class` keyword
Did you seriously just plug your blog post in es-discuss? Are you really explaining the open-closed principle and composition vs inheritance to a mailing list of people interested in language design? About why class is added: https://esdiscuss.org/topic/is-class-syntax-really-necessary ECMAScript would have looked different had it been designed from scratch today - but given your criticism everything apart from mixins for classes is impossible without breaking compatibility and mixins are being explored separately anyway. From: Eric Elliott e...@paralleldrive.com I've already posted this on my Medium blog here: https://medium.com/@_ericelliott/how-to-fix-the-es6-class-keyword-2d42bb3f4caf ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: iterator next method returning new object
Well, if the user caches the result (in order to pass it to another iterator) they'll get unexpected results. Iterator A yields: ```js {value: 1, done: false} {value: 2, done: false} {value: 3, done: false} {value: 4, done: false} ``` There are two consumers for the iterator (sending the result to remote servers that perform a calculation) which do something like: ```js function consume(){ var toSend = iterator.next(); if(toSend.done) return Promise.resolve(); return fetch(/mydata?id=+toSend).then(function(result){ return {value: toSend.value, response: result}; }); } ``` Returning a mutable object will cause a race condition which will cause incorrect results sometimes. Whether or not people will actually do this is an interesting question but IMO returning mutable objects is a big lose here. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Cancelable promises
From: Andrea Giammarchi andrea.giammar...@gmail.com AFAIK bluebird did: https://github.com/petkaantonov/bluebird /blob/master/API.md#cancelerror-reason---promise For what it's worth - bluebird is swapping its cancellation implementation in a week or two. You can read about it here: https://github.com/petkaantonov/bluebird/issues/415 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: How would we copy an iterator?
Why not? The generator would switch on sent value, in a loop. Well, let's say we have an iterator that does nothing once, returns what was sent to it the first 5 times and then is done: ```js function* gen(){ var res = yield; for(var i = 0; i 5; i++){ res = yield res; } } var iter = gen(), res = {}, i = 1; iter.next(); do { res = iter.next(i++); console.log(res.value); } while(!res.done); ``` How would you clone that with a switch? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: How would we copy an iterator?
Of course this example is contrived! It's the simplest example I could think of. I do think it stands for every example of any iterator that takes any input from `.send` or `.throw`. I have plenty of other contrived examples (implementing `fork` like this by using generators for coroutines with promises is at least mildly cool). That said I absolutely agree that more practical examples are required in order to make this already way-powerful two way protocol into something even more complicated. On Mon, Feb 23, 2015 at 9:11 PM, Brendan Eich bren...@mozilla.org wrote: Benjamin (Inglor) Gruenbaum wrote: Why not? The generator would switch on sent value, in a loop. Well, let's say we have an iterator that does nothing once, returns what was sent to it the first 5 times and then is done: ```js function* gen(){ var res = yield; for(var i = 0; i 5; i++){ res = yield res; } } var iter = gen(), res = {}, i = 1; iter.next(); do { res = iter.next(i++); console.log(res.value); } while(!res.done); ``` How would you clone that with a switch? The switch has to go on the inside -- the generator author has to cooperate with client code to make something that can be cloned. It could be this is too great a hardship, but we need more evidence, not contrived examples. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A Declarative replacement for toMethod
A programmer who wrote the assignment aPusher.push = MyArray.prototype.push was probably thinking that they could just reuse the push method from MyArray.prototype and that the super.push call within it would start searching for a push method at the [[Prototype]] of aPusher. But it doesn't. As a programmer - I wouldn't think it'd make that call. I don't think that it's safe to say most JS developer would expect `super` to call `Pusher` here. JS programmers are used to dynamic `this` and ad-hoc mixins but I don't think they would expect dynamic `super` when borrowing methods like that. I think people view `this` as context and `super` as an alias but time will tell. Care to share more interesting use cases for `mixin`? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Subject: Performance of iterator .next() as specified
In my testing (and in my theory, as an absolute) this is a real performance defect in the spec and it will make iterators inferior to all other forms of sequence iteration, to the extent that they may end up being used very rarely, and developers will be biased away from Map and Set as a result. Why? Allocating a new object isn't really expensive, in cases it is and it introduces GC pressure a clever engine can optimize it away by not really allocating a new object where it is not required. Your suggestion can be fully implemented by the engine already in the cases you speak of (where no reference is kept) so there is no real speed benefit from it performance wise. However in the case an iteration result is kept for later use this can be destructive and create unpredictable results. Also - of course for... of and iterating iterators right now is slower than iterating in ways that have been there for years. Modern JS engines usually add support for features and only then optimize them. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Subject: Performance of iterator .next() as specified
On Sun, Feb 15, 2015 at 3:06 PM, Katelyn Gadd k...@luminance.org wrote: In my testing Map and Set are outperformed by a trivial Object or Array based data structure in every case, *despite the fact* that using an Object as a Map requires the use of Object.keys() to be able to sequentially iterate elements. The cost of iterator.next() in v8 and spidermonkey is currently extremely profound and profiling shows all the time is being spent in object creation and GC. (To be fair, self-hosting of iterations might improve on this some.) Yes, this is of course true simply because iterating Set/Map was not optimized yet in V8/SpiderMoney since usually features are first implemented and then optimized. Benchmarking current naive engine implementations to make conclusions about the spec is a very risky thing to do. It's entirely possible for engines to optimize this. By the same logic I could say that `const` has bad performance because how it is currently implemented as much much slower than `var` in V8. I am sure that given some sufficient amount of compiler engineering, the allocations could be entirely optimized out, but this is far from a trivial case so odds are it will not happen soon. Right, I agree with you there it probably won't happen soon. Changing the spec won't change that fact. Remember that the engine doesn't actually need to allocate a new object in cases where it can reuse the old one safely since it's not used anymore - again, this can be solved at the engine level. My point is that for my current test cases, were the .next() allocation optimized out via a spec revision and *very trivial* change to current implementations, the performance would be great. The bottleneck would go away. This is much, much easier than having to introduce sophisticated escape analysis allocation removal into JS VMs. This is something that can be solved at the VM level. VMs perform much much smarter optimizations than this already. There is no reason to sacrifice code correctness and the principle of least astonishment in order to get acceptable performance. Benchmarking against proof of concept implementations is counter-productive in my opinion. The engines are already 'allowed' to use the same object when there is no observable difference. Even if we allow this 'optimization' it will take the engines as much time to implement it so there is no gain from this anyway. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Subject: Performance of iterator .next() as specified
This is actually exactly the kind of slow code Katelyn was talking about. Also, you probably meant `set[Symbol.iterator]()` and `for... of`. What Katelyn is talking about is optimizing .next in the example code to not return a new object but to return the same one every time with different values filled in. In order to optimize that with your transpiler you'd need to implement your own `Set` and `Map` because like Katelyn correctly noted `Set` and `Map` do not expose a fast way (in current implementations) to iterate them at the moment - at least until engines optimize them. Katelyn is arguing it would be useful to allow the implementation to return the same instance and I'm arguing the reason it's slow is because it's benchmarked against a slow implementation that was not optimized yet but can easily be - just like Katelyn noted as LuaJIT does. When I can get more sound abstractions for no additional cost (eventually) I'd rather not introduce implicit mutable state into the application. Developers won't be aware of it being mutating and the whole notion of a mutating-at-a-later-point return value is very error-prone in my opinion. On Sun, Feb 15, 2015 at 3:35 PM, joe joe...@gmail.com wrote: On Sun, Feb 15, 2015 at 7:16 AM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: This is something that can be solved at the VM level. VMs perform much much smarter optimizations than this already. There is no reason to sacrifice code correctness and the principle of least astonishment in order to get acceptable performance. Benchmarking against proof of concept implementations is counter-productive in my opinion. The engines are already 'allowed' to use the same object when there is no observable difference. Even if we allow this 'optimization' it will take the engines as much time to implement it so there is no gain from this anyway. __ Is 60,000 lines of source code a good enough proof of concept for you? I don't see what the problem is. My transpiler generators the following ES5 code: //for (var item in set) var iter = obj.iterator(); while (1) { var ret = obj.next(); if (ret.done) break; var item = ret.value; ...loop body } It works quite well. You may be right about the VM vendors, however. This requirement basically makes JS useless for anything other than minor scripting tasks. The VM people may not have any choice but to optimize it. Joe On Sun, Feb 15, 2015 at 3:35 PM, joe joe...@gmail.com wrote: On Sun, Feb 15, 2015 at 7:16 AM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: This is something that can be solved at the VM level. VMs perform much much smarter optimizations than this already. There is no reason to sacrifice code correctness and the principle of least astonishment in order to get acceptable performance. Benchmarking against proof of concept implementations is counter-productive in my opinion. The engines are already 'allowed' to use the same object when there is no observable difference. Even if we allow this 'optimization' it will take the engines as much time to implement it so there is no gain from this anyway. __ Is 60,000 lines of source code a good enough proof of concept for you? I don't see what the problem is. My transpiler generators the following ES5 code: //for (var item in set) var iter = obj.iterator(); while (1) { var ret = obj.next(); if (ret.done) break; var item = ret.value; ...loop body } It works quite well. You may be right about the VM vendors, however. This requirement basically makes JS useless for anything other than minor scripting tasks. The VM people may not have any choice but to optimize it. Joe ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Subject: Performance of iterator .next() as specified
Joe, I don't think we're having the same discussion. Again, this is about the issue Katelyn raised about the return value of `.next`. Katelyn suggested that the return value of a `.next` call in the iteration protocol - an object of the form `{value: value, done: boolean}` should be allowed to be reused between calls - so an iterator can return _the same_ object without allocating a new one. I argue (and from what I understand Kevin agrees with me) that allowing this is error prone and might cause surprises for developers since they have an object returned that has mutated implicitly without the consumer being aware. We can have the same performance gain by a clever engine that figures this sort of thing out itself. On Sun, Feb 15, 2015 at 4:13 PM, joe joe...@gmail.com wrote: Again, where does this mutation occur? The spec shouldn't allow any such thing to begin with; it should mandate exactly what my compiler does: as soon as .next returns, copy .value into the loop variable. The developer shouldn't have any access to the return value from within the loop at all; if he does, that should (ideally) be considered a violation of the standard. On Sun, Feb 15, 2015 at 8:09 AM, Kevin Smith zenpars...@gmail.com wrote: When I can get more sound abstractions for no additional cost (eventually) I'd rather not introduce implicit mutable state into the application. Developers won't be aware of it being mutating and the whole notion of a mutating-at-a-later-point return value is very error-prone in my opinion. Right. Mutating the returned object isn't really tenable from a usability point of view. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
ES7 property initializers
Looking at the syntax from here: http://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#es7-property-initializers ES7+ Property Initializers Wait, assigning to properties seems like a very imperative way of defining classes! You're right, however, we designed it this way because it's idiomatic. We fully expect a more declarative syntax for property initialization to arrive in future version of JavaScript. It might look something like this: // Future Version export class Counter extends React.Component { static propTypes = { initialCount: React.PropTypes.number }; static defaultProps = { initialCount: 0 }; state = { count: this.props.initialCount }; tick() { this.setState({ count: this.state.count + 1 }); } render() { return ( div onClick={this.tick.bind(this)} Clicks: {this.state.count} /div ); } } Also discussed here: https://github.com/6to5/6to5/issues/619 Are there any plans to specify this? Are there any proposals being worked on to specify syntax similar to this or alternative syntax addressing this? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Re: Aborting an async function
My questions is, how can we setup a function to abort a pending async function? That's an interesting question. Cancellation of promises is something that has been debated several times (not sure if at all in esdiscuss). There is a specification but there are many objections to it and some think it complects promises. Domenic is probably up to date on this. In your case you have several alternatives with the current API: - You can return a rejected promise whenever a `client` method gets invoked if it is in error state. - You can use promises directly rather than an async function which would probably give you finer grained control here. - You can pass a token into clients' methods ala c#'s CancellationToken and invoke it on errors to signal something bad happened from the outside. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Aborting an async function
Thanks, in case anyone is wondering this is the relevant result: https://esdiscuss.org/topic/future-cancellation On Tue, Feb 3, 2015 at 9:50 PM, Brendan Eich bren...@mozilla.org wrote: Benjamin (Inglor) Gruenbaum wrote: Cancellation of promises is something that has been debated several times (not sure if at all in esdiscuss). Many times: https://www.google.com/search?q=site%3Aesdiscuss.org%20cancel%20promise Google site: search is your friend. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Set and Map iteration order
Hi, I recently answered a question on StackOverflow about set iteration order which made me read the spec. I remember the recent Set.prototype.entries: indices as keys discussion but I couldn't figure out if the fact sets and maps are ordered on insertion order is specified is intentional and an artifact. The spec looks crafted in a way it looks intentional, for example in set: - Set.prototype.add always adds to the end of the entries list - Set.prototype.delete does not delete from the list but rather sets the value to `empty` - Iteration in %SetIteratorPrototype%.next iterates entries by index and in order. Am I understanding this wrong or is set iteration order specified (same for map)? Can anyone please refer me to previous discussions on this when the decision was made? I can't seem to find the relevant material and I'm interested in the rationale. Thanks again! Benjamin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Set and Map iteration order
We don't all have superpowers and know how to find targeted topics from 3 years ago :) (I did google search, I'll work on my list search-fu) On Tue, Feb 3, 2015 at 9:52 PM, Brendan Eich bren...@mozilla.org wrote: https://esdiscuss.org/topic/set-iterators (site: search again, but I admit I used deterministic and tyler close keywords to help.) /be Benjamin (Inglor) Gruenbaum wrote: Hi, I recently answered a question on StackOverflow about set iteration order which made me read the spec. I remember the recent Set.prototype.entries: indices as keys discussion but I couldn't figure out if the fact sets and maps are ordered on insertion order is specified is intentional and an artifact. The spec looks crafted in a way it looks intentional, for example in set: - Set.prototype.add always adds to the end of the entries list - Set.prototype.delete does not delete from the list but rather sets the value to `empty` - Iteration in %SetIteratorPrototype%.next iterates entries by index and in order. Am I understanding this wrong or is set iteration order specified (same for map)? Can anyone please refer me to previous discussions on this when the decision was made? I can't seem to find the relevant material and I'm interested in the rationale. Thanks again! Benjamin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Aborting an async function
Bluebird is actually overhauling cancellation in 3.0 - https://github.com/petkaantonov/bluebird/issues/415 for what it's worth we're not agreeing about syntax or how to make it better either :) For what little my opinion is worth here compared to the other people involved I'm favouring the single consumer -consumer cancellable counterpart for promise because of the arguments Kris and Domenic made about the inherent issues of multiple consumer cancellation. On Wed, Feb 4, 2015 at 1:31 AM, Domenic Denicola d...@domenic.me wrote: Yep, the first thing I noted with Bradley’s example is that there were some pretty extraneous try/catches. Everything inside `new Promise` that throws an error will cause the promise to reject, so no try/catch needed there. And similarly inside a promise handler you should just let the errors be caught. At the risk of turning this into code-review-discuss, my take on Bradley's function, without using async/await: ``` function fetchish() { return new Promise((res, rej) = { const client = new Client(); client.on('error', rej); resolve(client.get()); }) .then(JSON.parse) .then(f); } ``` (last few lines could equivalently be replaced by `resolve(client.get().then(b = f(JSON.parse(b` if you'd like.) -- Regarding cancelation, this has definitely been a desired feature for a long time. However I'm hesitant to dive into trying to standardizing something given that there are several competing ideas and no clear winner. (My leading candidates: a single-consumer consumer-cancelable TaskT counterpart to PromiseT; something similar to [this old Promises/A+ discussion][1], which I think is similar to Bluebird 2.x; something built on that but more complicated, including support for forking and similar; C#-style cancelation tokens; ...) I guess it seems likely that whatever we do will work for between 80-95% of cases and the remaining 5-20% will be unhappy. I think there's a lot of work to do to get that toward 95% instead of 80% though, and someone needs to champion it through that gauntlet. [1]: https://github.com/promises-aplus/cancellation-spec/issues/6 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Aborting an async function
Yes, the non-overlapping way to write it IMO would be to isolate the rejection on errors to a function: ``` let watchError = (client) = new Promise((resolve, reject) = client.on(error, reject)); // as a plain promise function fetchish(){ let client = new Client; return Promise.race([watchError(client), client.get()]).then(JSON.parse)); } // as an async function async function fetchish(){ let client = new Client(); let result = await Promise.race([client.get(), watchError(client)]); return JSON.parse(result); } ``` On Wed, Feb 4, 2015 at 1:16 AM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: to be honest that looks more like an all-in (good old events in the house) ... put a generator somewhere, please! /ignore-me I wonder if actually fetchish shouldn't be directly a Promise instead, feels like overlapping. Just random thoughts, curious to see more mixed async patterns in the real world Best Regards On Tue, Feb 3, 2015 at 8:26 PM, Kevin Smith zenpars...@gmail.com wrote: I would think that a hypothetical `client.get` method would reject when an error occurred, so that you wouldn't need to attach an error handler. That said, you can also freely mix promises with await and async: async function fetchish() { let text = await new Promise((resolve, reject) = { let client = new Client; client.on(error, reject); resolve(client.get()); }); return JSON.parse(text); } ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Informative notes
This looks sweet Domenic! Especially things like https://github.com/tc39/Array.prototype.includes/blob/master/README.md It would be great it if were standardised and made more readable (the sidebar for example) On Mon, Feb 2, 2015 at 11:43 PM, Domenic Denicola d...@domenic.me wrote: From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Brendan Eich Not bad -- we are using gists and github markdown but could build that up to mimic the PHP structure and style a bit, if enough people find value in it. FYI the new hotness is Ecmarkup + Ecmarkdown as in e.g. https://arv.github.io/ecmascript-object-observe/ or https://bterlson.github.io/Array.prototype.includes/ :) Regarding the general idea of motivation/introductory materials, I think the new process explicitly encourages this, and indeed most new proposals include that in their README or similar. Examples: - https://github.com/tc39/Array.prototype.includes/blob/master/README.md - https://arv.github.io/ecmascript-object-observe/#intro - https://github.com/rwaldron/exponentiation-operator - https://github.com/lukehoban/ecmascript-asyncawait We could consider trying to standardize but we're still in the exploration phase I think. Good to experiment and see what people like. (For example, I want to steal that sidebar-TOC from the PHP RFC.) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Informative notes
Not bad -- we are using gists and github markdown but could build that up to mimic the PHP structure and style a bit, if enough people find value in it. PHP's ircmaxell told me they're using WikiText - for example: https://wiki.php.net/rfc/combined-comparison-operator?do=editrev=0 It shouldn't be too hard to do something similar with markdown - although I think a centralised site similar to php's for holding all proposals currently discussed as well as a place for people to leave comments or directing them to this mailing list. I don't mind taking a shot at getting something like this up - would people use it? On Mon, Feb 2, 2015 at 11:10 PM, Brendan Eich bren...@mozilla.org wrote: Benjamin (Inglor) Gruenbaum wrote: For example - I don't need to know or understand what `[[ReferenceGet]]` is to understand something written in this sort of style: https://wiki.php.net/rfc/combined-comparison-operator Not bad -- we are using gists and github markdown but could build that up to mimic the PHP structure and style a bit, if enough people find value in it. BTW, that particular combined-comparison-operator proposal (the spaceship operator, =) has been discussed at TC39 meetings in passing. I think dherman is the likely champion, but I could be wrong! /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Informative notes
Follow-up thought: people still link to the (completely outdated) proposals on the wiki, because they are often very readable. I think people mostly link to them because they are rank pretty well in search results and are confined to a single problem in a readable way. I think the way PHP manages RFCs (https://wiki.php.net/rfc/) - while not nearly as accurate (IMO) as ES proposals has some really interesting things in its template and encouraging community feedback on proposals while they're worked on is very valuable. For example - I don't need to know or understand what `[[ReferenceGet]]` is to understand something written in this sort of style: https://wiki.php.net/rfc/combined-comparison-operator ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: a weird yield* edge case
I think that people would generally will _expect_ `yield *` to be have like yield inside a loop. So most people would expect: ``` yield* iterator ``` To behave like: ``` for(let val of iterator){ yield val; } ``` While I'm not (yet) suggesting that the behaviour should be similar in both cases this is definitely something to consider before deciding on throwing or suppressing. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: a weird yield* edge case
Oh, I completely agree that `yield *` is not just desugared into the above for...of loop form. I'm just saying that that's how most developers will likely look at it. Adding a while loop that calls the inner iterator's next with the same value wouldn't change what developers would expect here. I'm not arguing for one solution or another - just making the point that if it'll be anything like python's yield from - when developers _think_ of yield* they'll think of pumping an iterator from another iterator and expect the behaviour of throw to be similar. On Sat, Jan 31, 2015 at 9:14 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Jan 31, 2015, at 10:13 AM, Benjamin (Inglor) Gruenbaum wrote: I think that people would generally will _expect_ `yield *` to be have like yield inside a loop. So most people would expect: ``` yield* iterator ``` To behave like: ``` for(let val of iterator){ yield val; } ``` While I'm not (yet) suggesting that the behaviour should be similar in both cases this is definitely something to consider before deciding on throwing or suppressing. They are similar, but the transparency requirement of yield* has priority It's not a pure desugaring. For example, yield* passes throw the IteratorResu;lt objects produced by the inner iterator. The above desugaring can't do that. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Value Types shims/transpiler?
We'll probably talk about that tomorrow in a break-out. At least I hope to! Thanks, this sounds awesome. It's definitely one of the most awaited ES7 features and it's definitely highly applicable in a lot of code I'm writing (and in a lot I'm reading). If there is any help you guys need with testing the proposal out or writing tooling - please let the community know. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Value Types shims/transpiler?
Hey, I know ES7 value types are not yet done and are definitely not ready for prime time but I'd really like to play with them to get a hang of the API. I'll be working on a library that will likely take a while to build and will greatly benefit from them and I want to think about the API. Are there any tools for prototyping and experimenting with ES7 value types under the current idea of what the API will be? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Math.TAU
I'd just like to add that joke requests like Math.TAU that have no place in the language specification itself generate a considerable amount of overhead for those of us who keep up with the mailing list. Especially since the other topics discussed are interesting (e.g. ModuleImport ). I think it would be best if we refrain from them in the future as this mailing list is already noisy. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Value Types as map keys in ES7
I'd like to raise an issue with ES7 value objects with maps raised here: http://esdiscuss.org/topic/maps-with-object-keys To save you all time, let me sum things up: ES6 maps don't solve a particular (but common) issue for me - using compound objects as keys. I do a lot of statistical analysis and I need keys to be compound tuples or other values. This is currently not possible with ES6 since map key equality is checked with `===` so it is always reference equality ES7 introduces value objects - which are really cool anyway. This allows for compound keys.which partially solves my issue because value keys are compared structurally with `===`. However, it does not let me index on partial information (described in my last commend on that issues). Since it is impossible to override `===` in value objects from what I understand - It would be impossible for me to use partial objects as keys. To illustrate, if for example I have a lot of 10 dim vectors, and I want to index them as keys based on their first two dimensions - it is impossible at the moment and I have to project them into their 2d counterparts which have no further use for me. Is this somehow addressed? I'm unsure where to look for answers. It seems natural to me to allow specifying a hashing function in the `Map` constructor (rather than on every type) to solve this particular (but again, rather common in code that does crunching) problem. Thanks, Benjamin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Maps with object keys
I'm trying to work with ES6 Map objects and I ran into an interesting problem. I want to index/group based on several key values. Let's say my original data is something like: ```js [{x:3,y:5,z:3},{x:3,y:4,z:4},{x:3,y:4,z:7},{x:3,y:1,z:1},{x:3,y:5,z:4}] ``` I want to group it based on the x and y property values, so I want the result to look something like: ```js {x:3,y:5} == {x:3,y:5,z:3},{x:3,y:5,z:4} {x:3,y:4} == {x:3,y:4,z:4},{x:3,y:4,z:7} {x:3,y:1} == {x:3,y:1,z:1} ``` However, as the docs and draft say maps detect existence ( `Map.prototype.has ( key )`) for object the same way `===` works for objects (specified in `SameValueZero(x, y)`). I really don't see how to solve this other than implementing my own form of hashing for these specific objects and 'rolling my own' logic here (instead of working directly with `Map`s). For comparison - in Python for example I'd use a dictionary with tuple keys. So I'm wondering, what's the point of being able to use object keys in `Map` objects if the equality check performed is reference equality? I feel like I'm either missing something obvious here or we have a usability issue on our hands. Benjamin (Also asked in SO http://stackoverflow.com/questions/21838436/map-using-tuples-or-objects ) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Maps with object keys
My issue here is that I want to index on complex values. I was under the impression ES6 maps solve amongst others the problem that with objects - keys are only strings. I want to index on 2 (or 100) properties - in this example the x and y values. I don't want to iterate the whole collection and all the keys every time I check for existence - that's very inefficient. Moreover, I don't want to write a for loop over the entries every time I check for existence - if I wanted that I'd just use an array. Also note, we're talking about the _keys_ of the map and _not_ the values. BTW in Python (which I reiterate is just an example) it's done via a hash function ( https://github.com/python-git/python/blob/master/Objects/tupleobject.c#L290) that's not the issue though. On Mon, Feb 17, 2014 at 11:43 PM, Bradley Meck bradley.m...@gmail.comwrote: I understand the capability of python, but that is done through comprehensions that do not relate to the mapping of key to value. In ES6 the syntax comes out to: ``` let tuple = {x:3,y:5} [for (value of map.entries()) if (Object.keys(tuple).every((tupleKey)=tuple[tupleKey] == value[tupleKey])) value] ``` A quick comparator function for tuple like objects would be more clear than comprehension that does not relate to the mapping of key to value. Notice how the keys of `map` are never used in the comprehension. On Mon, Feb 17, 2014 at 3:35 PM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: Hi, when you reply please reply to the list (that is, include esdiscuss in the list of recipients) - otherwise I'm the only one who can read your mail. As for your question, You might want to look into how maps (or dictionaries) work in languages like Python where you can have a dictionary with tuple keys for example which would let me index on `(x,y)` values. This is of course a very 'simplified' example of what I'm actually doing (statistical learning). On Mon, Feb 17, 2014 at 11:31 PM, Bradley Meck bradley.m...@gmail.comwrote: What you are describing is a Set/Array of data that runs a filter at runtime. Could you go into some detail on why a filter on sets/arrays does not make sense for your use case? I am unsure what the original mapping of key (during .set(key, value)) to value would represent if keys are treated as many-many filters rather than 1-1 relationships for Maps in ES6. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Maps with object keys
Thanks, I was starting to feel like I wasn't explaining my issue very well given the other replies. I'm glad we agree this is not something user-code should have to shim for language level collections. I'm working on several projects that perform statistical analysis and I wanted to stick to JavaScript, this makes it really hard to do so. It effectively renders `Map`s useless for me exept for readability purposes. Also, thanks for the straight up 'this is still a problem now' - it probably saved me a considerable amount of time. Value types do sound like a better solution than throwing `equals` and `hash` on every object, it is conceptually similar to the solution I've got so far (using a flyweight to enforce uniqueness and generate 'value objects'). (Of course the current solution has memory issues which I need to be careful about - but I hope I'll manage) I do think there might be a problem with value types (or rather, value objects) for key though - if I followed correctly, value types do not allow you to specify `===` and `!==` yourself, they are a recursive structural equality test which limits your ability to ignore properties you do not care about. For example, getting points that are unique points on the R2 (x,y plane) by throwing R3 points (x,y,z) into a set with x,y equality and then extracting them. I'm not sure if this was discussed or if it's a big enough issue but I think it's worth talking about. Thanks, Benjamin On Tue, Feb 18, 2014 at 4:50 AM, Jason Orendorff jason.orendo...@gmail.comwrote: On Mon, Feb 17, 2014 at 3:09 PM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: I'm trying to work with ES6 Map objects and I ran into an interesting problem. Yes! Well done. We've noticed this too, and considered (a) allowing objects to provide their own hash and equals operations, as in Java and Python; (b) allowing the Map user to specify hash and equals operations for the Map at construction time. These were rejected partly because both ideas would make Map behavior observably nondeterministic, or else overspecify. Also because object hash codes would be exposed to users, and ensuring that those do not leak any information about object addresses would likely make them slow. The solution that prevailed is (c) introduce value types in ES7. With value types, you'll be able to declare an aggregate value type, much like a Python namedtuple, to use as your Map key. Values of that type can be compared for equality with ===, like Python tuples, and Map will work accordingly. Until value types are spec'd and implemented, the other workarounds already mentioned in this thread will have to do, I'm afraid. -j ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Merging Bind Syntax with Relationships
When you asked about discussion and this ran into my mind :) I remember it was discussed here http://esdiscuss.org/topic/protocol-library-as-alternative-to-refinements-russell-leggett, ( the syntax in https://gist.github.com/genericallyloud/7086380 ) Do the semantics proposed above work with what's proposed there? The using the function as an extension method seems pretty similar. However , Russell's work proposes a form of polymorphic dispatch based on the extended type. For example: ```js let dmot = new DoingMyOwnThing(Bob); dmot::map( n = n * 3;) // calls method `map` of the DoingMyOwnThing class instead of using the protocol method ``` This is really useful behavior that solves a few very real problems for me (it's real extension methods) - I think it would be very beneficial for discussions about bind syntax to allow or at least consider this. Thanks, Benjamin On Thu, Feb 13, 2014 at 10:33 PM, Kevin Smith zenpars...@gmail.com wrote: What about protocols? Can you elaborate? I know that Russell Leggett did some work along those lines a while ago (which really inspired the merge idea), but can you describe exactly what you mean? Note though, that since behavior of `referenceGet` is completely arbitrary, you could (for instance) create a reference name object which traverses up the prototype chain looking for a certain method name, and returns some fallback method if nothing is found. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: Subject: Another switch
I'm new too, but don't think that's exactly how things get proposed here :) Spec changes don't start with solutions - they start with existing problems you're trying to solve. For example. In ES6 I might do ```js var res = ({ hello : () = 12, /* no fallback */ world : () = 323, /* no fallback */ ... })[ myWord] ``` Or just an if, or other things. The cost of adding a keyword into the language is big (you're breaking any code that uses that keyword as an identifier which is a lot). My suggestion is that you make a static analysis tool that warns people about switch fallthrough and then advocate it. Tools like jshint/jslint will warn you about it, using such tools can (and should IMO) be a part of your build and release process. Thanks, Benjamin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promise.cast and Promise.resolve
On Sat, Feb 8, 2014 at 2:57 PM, Quildreen Motta quildr...@gmail.com wrote: Well, promises are a fairly old concept, with several different implementations throughout the history of CompSci, and even in JavaScript land itself. `.chain` itself is not common because it doesn't need to have that name, but it is a common operation (`.then` encodes that operation, for example, but you can't control when it gets applied). As for working implementations of `.chain-able` promises, you can see: https://github.com/folktale/data.future#example, and https://github.com/fantasyland/fantasy-promises, although they are not Promises/A+, it should be easy enough to implement `.cast` and `.then` on top of those primitives. Phew! After that first sentence I thought I was getting a link to Liskov's paper(s) :) Both those libraries seem to have a low number of users, very few mentions and almost zero users in npm. I was not implying that it's impossible to implement chain, or monadic promises - I was implying very few people use them in JavaScript. Where, on the contrary people use the current model extensively in APIs. The debate from what I can tell is about standardizing something that exists but is not used nearly as much over something that exists and used extensively. There are three things you want to do with a promise: - You want to sequence asynchronous computations, such that you can specify computations that depend on a particular value. This is what `.chain` does. - You want to transform the value of a computation, but the computation itself is synchronous. This is what `.map` does, and `.chain` can generalise `.map`. - You want to assimilate the result of a different promise. This is what `.cast` does. Unfortunately, Promises/A+ only provide you with a `.then` method, which does all of those things for you, but you can never control which of those gets applied. Thus, `.chain` is a more general approach, and `.then` can be easily derived from `.chain`. A specification should favour the general use cases to make it easy for people to write more specific computations in userland, instead of constraining the expressive power to particular higher-level use cases. This is what the discussion on Promises right now is about. I'm not saying that `.chain` is a better or worse proposal here (or what I think at all). I'm talking about programmers in practice - those people in userland that are performing computations you speak of? They had a choice and they chose `.then`. Promise libraries such as Q (but not only) have been evolving for several years now. The way `.then` works was subject to change many times before but people in practice have found '.then' to be a simple and working solution. (For the record, when I think of .map I don't think of a synchronous computation - in fact I don't see that the fact the computation is synchronous in a promise chain is irrelevant - but again, this is not about _my_ opinion) One of the problems with just following existing solutions is that you'd also be copying the evolution mistakes and technical debts in those solutions. The committee **is** considering the existing solutions, and the use cases presented by people, which is a good thing. For example, for the asynchronous map use case, `.then()` is not usable short of adding plenty of special cases, and special cases don't compose cleanly. Standards are difficult because what you decide will shape the solutions that people write in the language for decades, standards evolve slowly, that's why you have less chances to make mistakes -- in a library you can make a mistake and promptly fix it in the next version, this is not true of standards. My problem with that paragraph is that promise libraries _have_ evolved for years. There are several libraries - Bluebird, Q, when, RSVP or any other promise library with _a lot_ of dependent libraries on NPM and more than a thousand stars on GH. They're all open source and At any point anyone could have: - Add 'chain' with a PR, explain why it's better and convince _any one of those_ maintainers why it should be added. I've seen work in Promise libraries several times. - Open an issue with convincing real life use cases and explain them - advocate .chain and get people to use it. I've seen this work in promise libraries several times and have done so myself. - Fork any one of them (most, if not all have permissive MIT licenses) and replace .then with .chain (or add it). It's also no problem to interop with existing A* libraries. - Build a new library and get users - I personally recently converted over 100 KLOC to use a promise library that didn't exist a year ago. I'd just like to add I did not make (at least intentionally) a single technical argument here. It's merely the process I'm concerned about. Choosing APIs that have no extensive use in the ecosystem over ones who do without first battle testing them concerns me.
Re: Behavior of `eval` in non strict mode.
Thanks, this clarifies things. I'll update the answer on SO to reflect the findings. On Thu, Jan 9, 2014 at 3:54 AM, André Bargull andre.barg...@udo.edu wrote: Thanks for the reply. I'd actually expect `undefined` because function declarations does not return anything. Converting it to a function expression kind of misses the point since those are well... expressions :) I've tried looking in all the relevant places in the spec but still couldn't unambiguously figure out which browser is 'correct'. There are a few edge cases in reference resolution which are not correctly implemented in most browsers. Your example is basically the same as test case 2 from https://bugs.ecmascript.org/show_bug.cgi?id=1751. The relevant section in the specification is 12.13.4 Runtime Semantics: Evaluation: The left hand side of an assignment is always evaluated before the right hand side. This includes resolving and remembering the reference information for an identifier reference. In this case the identifier reference resolves to a binding on the global object, so assignment must be performed on the global, even if a (direct) eval expression introduces new bindings with the same name in the current scope. - André ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Behavior of `eval` in non strict mode.
I've recently run into this question in Stack Overflow: http://stackoverflow.com/q/21008329/1348195 ``` function f() { f = eval( + f); console.log(Inside a call to f(), f is: \n%s, f);} f(); console.log(After a call to f(), f is: \n%s, f); ``` What should the output of the following be? I expected `undefined` on both but that's because I'm used to strict mode. IE/Chrome treat this differently from Firefox and to be honest when I checked the spec it boiled down to which context is affected here. In IE/Chrome the eval is creating `f` inside the context of `f` acting like a function declaration inside. In Firefox it's acting like it's running in the global context. Which is correct? I've tried to follow 10.4.2 (or 18.2.1 in the ES6 draft which is nice) but I still couldn't figure out what if there is no calling context means. Thanks, Benjamin Grunebaum ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Behavior of `eval` in non strict mode.
Thanks for the reply. I'd actually expect `undefined` because function declarations does not return anything. Converting it to a function expression kind of misses the point since those are well... expressions :) I've tried looking in all the relevant places in the spec but still couldn't unambiguously figure out which browser is 'correct'. On Thu, Jan 9, 2014 at 1:53 AM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: looks rather an eval gotcha but I think Firefox is correct anyway. try `f = eval(( + f + ));` instead and it should produce what you expect (I guess) Regards On Wed, Jan 8, 2014 at 3:37 PM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: I've recently run into this question in Stack Overflow: http://stackoverflow.com/q/21008329/1348195 ``` function f() { f = eval( + f); console.log(Inside a call to f(), f is: \n%s, f);} f(); console.log(After a call to f(), f is: \n%s, f); ``` What should the output of the following be? I expected `undefined` on both but that's because I'm used to strict mode. IE/Chrome treat this differently from Firefox and to be honest when I checked the spec it boiled down to which context is affected here. In IE/Chrome the eval is creating `f` inside the context of `f` acting like a function declaration inside. In Firefox it's acting like it's running in the global context. Which is correct? I've tried to follow 10.4.2 (or 18.2.1 in the ES6 draft which is nice) but I still couldn't figure out what if there is no calling context means. Thanks, Benjamin Grunebaum ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: About Array.of()
From: Shijun He hax@gmail.com Subject: Re: About Array.of() This is an old thread which I like to mention again. The proposal is change the method name from Array.of() to Array.fromElements() to make it clear especially for non-English native programmers. `Array.of` sounds a lot more expressive than `.fromElements` to me. Optimally I'd like the array constructor to just accept a collection and convert it to an array but that's not going to happen. Would you mind explaining the issue here for non native English speakers? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: About Array.of()
Array.of sounds expressive only for native speakers. English is not my first language and it sounded expressive to me. I've asked 5 random friends that code and they all said it sounded fine to them. While that's not real evidence, it still shows that the only doesn't hold here. The only valid use case of Array.of is high-order function. No it's not. The main use case I see is converting array like structures (like NodeLists) to arrays without having to do that dirty `Array.prototype.splice.call` call: Array.of(document.querySelectorAll(.bar)) Higher order functions are a real use case but for sure not the only one. I completely agree with Rick that fromElements is confusing for the API __especially__ that creating an array out of actual DOM Elements _is_ a use case and it implies that it only works for _that_ use case. Like I said, the _optimal_ thing would have been to be able to do `Array(arrayLike)` and have it just work and create a new array from that collection (like collections tend to do in Java, C#, Python etc) but it's too late for that. That breaks ES (Array([1]) returns [[1]]). Array.of seems very close of that, you make an array of the items passed. The fact it's a static method makes it very clear that that's what it does IMO (although personally I'd favor putting it somewhere else). On Wed, Dec 18, 2013 at 9:01 PM, Shijun He hax@gmail.com wrote: On Thu, Dec 19, 2013 at 12:08 AM, Rick Waldron waldron.r...@gmail.comwrote: `Array.of` sounds a lot more expressive than `.fromElements` to me. Agreed. 1) Array.of sounds expressive only for native speakers. Non native programmers will have no idea about Array.of method, because they never seen such named method with such usage in any codes of any programming languages before (at least I never seen), if you search `array.of` in github, you will see many `array of int` `array of byte` `array of strings` `array of Book` or `array of Point`... in code or comments. 2) In fact such expressive is MEANINGLESS because we will never write `var a = Array.of(1, 2, 3)` instead of `var a = [1, 2, 3]` The only valid use case of Array.of is high-order function. So what's the readability of `foo(bar, array.of)` ? I just find that Dave Herman already pointed out this problem in the original thread: That said, the readability story you and I tweeted about is not so compelling given that, in the first-order usage pattern an array-literal is strictly more readable. So a longer name like Array.fromElements or something might be okay. Interesting that Dave (native speaker) and 程劭非(a non native speaker which suggest this name in this thread) both choose fromElements in the first place. Additionally, `fromElements` will also be confusing when the new DOM `Elements` API arrives: http://dom.spec.whatwg.org/#elements Well, even it's confusing it's still better than `of` for the use case, and some other alternatives: Array.fromItems // fromXXX has another benifit that alternative constructors (String.fromCharCode, Array.from) all begin with `from` Array.fromList Array.fromArguments Array.newArray Array.makeArray Array.theFixedConstructorWithoutGotchas I like the last one ;) what about you? Optimally I'd like the array constructor to just accept a collection and convert it to an array but that's not going to happen. Would you mind explaining the issue here for non native English speakers? The specification reads: Array.of(...items) Which, when said out loud is: Array of items Even `Array.ofItems` is better than `Array.of` for the only use case: foo(bar, Array.ofItems) I don't know how much clearer that can get. Bikeshedding the name of an API at this stage in ES6's progress is not a valuable use of anyone's time. Come on, there are only two things in Computer Science: cache invalidation and naming things. And if we don't fix bad names in this stage, we will lose the chance for ever. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: `String.prototype.contains(regex)`
I agree both with what Jason said and what Andrea said, It needs to be consistent and I think the way Andrea suggests is the correct one. If anything, I'd expect all of them to throw when passed multiple arguments for forward compatibility. It might be useful to check multiple values in contains/endsWith/startsWith or constrain it in some way. Benjamin On Wed, Dec 18, 2013 at 11:59 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: then none of them should throw, imho startsWith is like dropping the `/^` form a `RegExp`, endsWith like dropping the `$/` part .. that's it The problem with RegExp is usually the safe escaping, having 1 char less to type for a `.test()` - so actually counting chars in the method name is even more - is not a win In `/^th(is|at)$/.test(str)` the useful `RegExp` part is in the middle so what was the reason to not coerce to string as basically every other `String.prototype` method does already if consistency was actually the reason ? Is it because split accepts `RegExp` too ? 'cause that's completely different scenario. On Wed, Dec 18, 2013 at 1:01 PM, Jason Orendorff jason.orendo...@gmail.com wrote: On Wed, Dec 18, 2013 at 11:16 AM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: May I ask what String.prototype.contains accomplish with a regular expression (that we don't already have with `RegExp.test`)? Consistency with the other methods, maybe? It would be bad API design to insist on there's only one way to do it at the expense of consistency and the principle of least astonishment. -j ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: ES5/ES6 methods on constructor functions instead of prototype
How would you define Array.isArray on the Array prototype? That'd just fail for everything that is not an array and doesn't implement isArray itself. Things like Object.keys are reflective, enumerating over the properties of an object (even more so in ES6) is not something you'd commonly do in the 'application level'. We have `Map`s now :) Benjamin -- Forwarded message -- From: Oliver Joseph Ash oliverj...@icloud.com To: es-discuss@mozilla.org Cc: Date: Mon, 16 Dec 2013 23:24:31 + Subject: ES5/ES6 methods on constructor functions instead of prototype I'm noticing that many methods added in ES5 and due in ES6 are defined on the type's constructor function instead of on the type's prototype. For example, Object.keys, Object.defineProperty, and Array.isArray. Is there a reason these were not added to the prototype, i.e. Object.prototype.keys, for consistency? Best, Oliver ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Try/catch conditional exceptions in light of generators
Here's how I see this post: - Performing Evented I/O well is one of the biggest use cases of JavaScript - in the browser, in mobile apps, on the server and generally. - Exceptions in I/O scenarios did not traditionally post a problem since constructs like callbacks and promises were used. - Generators were introduced in ES6, allowing developers like me to write code without needing many of those constructs. This fundamentally changes the way I can write JavaScript. - With generators, I can write try/catch clauses using the native language syntax. That's nice. - Try/catch clauses don't have any form of guards in ES, meaning I can't really catch logic errors and syntax reference/errors differently in a nice way. When adding I/O errors to the mix the problem gets magnified times 100 as my first example shows. I'm not even saying I think `catch(e if` is the solution. I'm not saying I have a solution I'm content with. I'm not even saying I have a solution at all. If it sounds like I was saying everyone should just implement catch.. if right way then I apologize for that and it wasn't my intent. This is why I posted: - Hey, I'm having the issue, are you having it too? Is it a real problem? - If so, are there clever ways to deal with it? - If so, what are they, are there proposals on the way? - If so, since this is an important issue to me, how can I promote it being addressed? I think that the first of these has been established, there was a suggestion raised about the third and I have no idea about the fourth. I do however, admit that the patterns proposal doesn't sound to me like it has enough to solve this use case, or that I understand how the two are that connected (which is what I tried saying in that post). On Thu, Nov 21, 2013 at 11:34 PM, Jason Orendorff jason.orendo...@gmail.com wrote: On Thu, Nov 21, 2013 at 12:55 PM, Brendan Eich bren...@mozilla.com wrote: So, we need the well-championed, thought-through, pattern-matching proposal first. It won't take too long, I bet, and in any event you are *not* going to get browsers implementing catch-if quickly -- I am 100% sure of this, based on long experience. And amen to that. Benjamin, adding one language feature for every reasonable use case presented on es-discuss sounds like a great way to get a language full of incoherent hacks in a hurry. That is, I don't think you'd like the result you're asking for, if you just directly extrapolate that to everyone else's JS pain point that can be addressed with one tiny leetle waffer-thin bit of syntax. A platform can have a hundred thousand APIs. A programming language can't have a hundred thousand features. The complexity budget is finite. We've got to add language features that work in multiple syntactic contexts and support multiple use cases. -j ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Try/catch conditional exceptions in light of generators
Thanks Brendan, Refutable patterns not being near consensus sounds like getting this done could be a lot of work both implementing it and figuring out a proposal people agree on. Maybe I'm understanding it wrong, but the related bit is: ``` GuardedPattern(refutable) ::= Pattern(refutable) if AssignmentExpression ``` Where all I really need to solve this problem is: ``` catch ( IdentifierName if AssignmentExpression ) ``` Adding a Pattern to a catch, while it sounds fancy (I'm all up for patterns!) is something that can be done either in addition to, or on top of something like `if AssignmentExpression` bit - it's not a part of the current proposal either. I really appreciate your time, effort and knowledge on this. You've been nothing but nice, and a great help for me when discussing issues here. Given how everyone I talked to here and in forums like the idea of stronger catch clauses and assuming you're already up for better catch clauses - who do I need to convince that this is a real use case? Can I take a look at the `catch (e if) {` proposal? Is it available online? What were the objections to it? Thanks, Benjamin On Thu, Nov 21, 2013 at 9:37 AM, Andreas Rossberg rossb...@google.comwrote: On 21 November 2013 01:55, Brendan Eich bren...@mozilla.com wrote: Benjamin (Inglor) Gruenbaum wrote: You tell me I don't need to sell you this - who do I need to sell this to? What people do I convince in order to have better catch clauses that solve my problem in the spec? I think we need a champion for the pattern matching strawman. Dave was championing but may need a tag-team partner. Cc'ing him. I can do that. I wanted to take it up anyway. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Try/catch conditional exceptions in light of generators
implications, though, as you'd presumably need to support multiple guarded catches, and behavior for a failed guard is different in the try/catch scenario than with parameters or properties. [1] http://wiki.ecmascript.org/doku.php?id=strawman:guards On Wed, Nov 20, 2013 at 10:24 AM, Brendan Eich bren...@mozilla.comwrote: Benjamin (Inglor) Gruenbaum wrote: Hi, thanks for the comment and sorry for the unclarity. I was refering to my original post in this thread about try/catch with generators: http://esdiscuss.org/topic/try-catch-conditional- exceptions-in-light-of-generators#content-0 Yes, but the Domenic pointed out that the reference error there has nothing to do with generators so much as async control flow in general (it could be in a function passed as a callback or downward funarg, and called later by any means). And you seemed to agreed. It's true that yield allows part of a function to run in a later event loop turn -- or just in a later iteration of a loop in the same turn. Generators by themselves are not async in the event loop sense. So first you need to identify the problem precisely. If you write function f() { ... setCallback(function g() {... RefErrHere ... }) ... } you need test coverage over the body of g. If you write function* f() { ... yield; RefErrHere ... } same deal. There is no difference in kind. So, is the problem you are citing a general one of test coverage over async control flow? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Jeremy Martin 661.312.3853 http://devsmash.com @jmar777 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Better a little with righteousness than much gain with injustice. Proverbs 16:8 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Try/catch conditional exceptions in light of generators
Honestly I'm really not sure how I feel about this. Guards are a huge deal. They're a big (and nice!) feature, it sounds like they bring a lot of complexity (specifying them, not using then). They'll likely require a lot of work and debate in order to make it in (or not). I have a very real and very simple use case I run into constantly. Like you said - if I used Mozilla's JS engine I'd be able to do a conditional catch but I don't have the luxury of only developing for Mozilla (I'll use it in Firefox OS for sure though :) ). For example, I write a lot of node which doesn't have conditional catch. (I completely agree about type conditions not being the right solution - behavior seems like a much better option) You tell me I don't need to sell you this - who do I need to sell this to? What people do I convince in order to have better catch clauses that solve my problem in the spec? Thanks, Benjamin On Wed, Nov 20, 2013 at 10:56 PM, Brendan Eich bren...@mozilla.com wrote: Sam Tobin-Hochstadt wrote: On Wed, Nov 20, 2013 at 12:35 PM, Brendan Eichbren...@mozilla.com wrote: I don't quite understand what Benjamin is running into. I think that Benjamin's point is that generators allow you to use synchronous programming models instead of async ones. Then your errors become exceptions instead of errback calls. So, whereas ES5-style JS features very few exceptions, ES6-style will feature more exceptions. This increases the pressure on exception handling to be nice, which it isn't because of the lack of catch guards. Yeah, if you read up, you'll see that this became clear just recently in-thread. Yay for refutable patterns, including in catch heads. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Up to date list of TC39 members?
Hi, I was wondering where I could get an up-to-date list of TC39 members. I know of http://tc39wiki.calculist.org/about/people/ but I'm not sure it is up to date. Thanks, Benjamin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Try/catch conditional exceptions in light of generators
Any form of reply on this question/problem would be highly appreciated. I believe this is a real use case and I'd like to know what other people think. I've had to deal with this multiple times since I sent this to es-discuss. On Tue, Nov 5, 2013 at 5:39 PM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: That's a good question. I try to discuss problems I run into. Developers, me included have found ways to minimize reliance on try/catch in synchronous operations using monadic maybies and checking values. It's very often in JavaScript that I want to handle exceptions that are related to I/O and/or external resources. In JavaScript these operations are almost always asynchronous. It's very common to handle the issue of asynchronously handling exceptions using the mechanism that is used to wrap the asynchronous operation. - If it's a callback people typically use the `(err,` first parameter convention. - If it's a promise people use a rejected callback, a common (but not the prettiest) example is `.fail` in jQuery. Both these options don't suppress things like syntax errors, reference errors etc. There are of course other ways to do asynchronous operations and I/O but more generally, mechanisms that go around the language error handling constructs do a pretty good job at this. Generators give me a new great way to do concurrency, they reduce code and increase readability. However - they bring me back to the try/catch of the language which does not make the distinction or allow me address the issue without wrapping the catch with more code. On Tue, Nov 5, 2013 at 5:04 PM, Domenic Denicola dome...@domenicdenicola.com wrote: I am curious what, if anything, about this problem has to do with asynchronicity? That seems to be a key part of your point, but I don't understand why you wouldn't phrase the problem entirely in terms of synchronous operations since nothing seems unique to async. On 5 Nov 2013, at 09:48, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: Traditionally, JavaScript code contains some sort of asynchronous logic either on the client side or on the server side. This makes the `try/catch` construct non-practical for many real use cases because it can not catch errors caused by callbacks and/or other asynchronous operations involved. This is why we have common idioms like the `(err,result)` of NodeJS callbacks or reject in promises implementations and so on. NodeJS also introduces domains which let you catch all errors that originated from a piece of code in a certain way. ES6 Generators recently implemented in NodeJS allow us to do concurrency using coroutines. This allows for very nice code that's very readable in certain cases. The async_functions proposal is also very interesting solving the problem without needing a runner for the generator. However, one issue arises from using generators for such concurrency. The current way try/catch works with generators does not give us a way to differentiate things like syntax errors from logic errors. Consider the following piece of code using Bluebird promises: ``` Promise.coroutine(function *(){ try{ let db = yield DBEngine.open(northwind); let result = yield db.query(SELECT name FROM users) return res; } catch (e){ //code to handle exception in DB } }); ``` Noticed the `ReferenceError`? Not obvious at first glance. A compile time tool _might_ find it but I may have a closure variable named `res`. This might even happen later when making changes. A catch-all does not do a good job here. What I'd want to do is to catch all exceptions that are _mine_. I need a way to catch exceptions of a different type. This is a real need in light of the new found usage for try/catch given generators. I've looked around and found one possible solution using catch guards ( http://wiki.ecmascript.org/doku.php?id=strawman:catch_guards ) , I know Firefox supports catch guards but I was unable to find anything in the specification or in the mailing list when searching relating to it. Petka added: Without predicated catch clauses you would need to write something like this: ```js Promise.coroutine(function *(){ try{ let db = yield DBEngine.open(northwind); let result = yield db.query(SELECT name FROM users) return res; } catch (e) { if( e instanceof RejectionError ) { //code to handle exception in DB } else { throw e; } } }); ``` The manual rethrow can easily be forgotten to be written ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Try/catch conditional exceptions in light of generators
Hi, thanks for the comment and sorry for the unclarity. I was refering to my original post in this thread about try/catch with generators: http://esdiscuss.org/topic/try-catch-conditional-exceptions-in-light-of-generators#content-0 Now that I started working more with generators - I find handling exceptions really difficult now that I use try/catch in a synchronous way. Just to be clear - I'm not suggesting a fix, I'm raising an issue me and some of my colleagues I've been facing and I'm interested to know if: - There is a consensus that this is a problem. - It's a big enough problem for other people too or it sounds like a big enough problem in case they have not tried coding asynchronous code with generators yet. - Someone already solved this, in which case I'd love to learn how (and share that knowledge on the MDN wiki). In case the code in the original post is unclear please let me know and I'll try to add a clearer sample. Thanks, Benjamin On Wed, Nov 20, 2013 at 1:03 AM, Brendan Eich bren...@mozilla.com wrote: Benjamin (Inglor) Gruenbaum wrote: Any form of reply on this question/problem would be highly appreciated. I believe this is a real use case and I'd like to know what other people think. I've had to deal with this multiple times since I sent this to es-discuss. Can you show exact code excerpt with a comment-pointer to the buggy bit, and then talk about the fix? It's really not clear what your this refers to. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
From: Allen Wirfs-Brock al...@wirfs-brock.com One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. I'd just like to say that I wouldn't rule out a creative solution that'd allow better function overloading. The problem is not the fact the arguments number isn't reachable without the context decided arguments imho. The problem is that overloading is something that is very useful to do, and we'd like to be able different functions based on the number of parameters. While optional parameters, and rest parameters are really useful and solve a lot of the use cases we'd need overloading for - it's clear that there are use cases it does not address. I'm not sure that tackling the problem by adding new syntax for the number of params is the best approach (although I'd hate to have to resort to arguments, explicitly or implicitly like in the example given). ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Try/catch conditional exceptions in light of generators
Traditionally, JavaScript code contains some sort of asynchronous logic either on the client side or on the server side. This makes the `try/catch` construct non-practical for many real use cases because it can not catch errors caused by callbacks and/or other asynchronous operations involved. This is why we have common idioms like the `(err,result)` of NodeJS callbacks or reject in promises implementations and so on. NodeJS also introduces domains which let you catch all errors that originated from a piece of code in a certain way. ES6 Generators recently implemented in NodeJS allow us to do concurrency using coroutines. This allows for very nice code that's very readable in certain cases. The async_functions proposal is also very interesting solving the problem without needing a runner for the generator. However, one issue arises from using generators for such concurrency. The current way try/catch works with generators does not give us a way to differentiate things like syntax errors from logic errors. Consider the following piece of code using Bluebird promises: ``` Promise.coroutine(function *(){ try{ let db = yield DBEngine.open(northwind); let result = yield db.query(SELECT name FROM users) return res; } catch (e){ //code to handle exception in DB } }); ``` Noticed the `ReferenceError`? Not obvious at first glance. A compile time tool _might_ find it but I may have a closure variable named `res`. This might even happen later when making changes. A catch-all does not do a good job here. What I'd want to do is to catch all exceptions that are _mine_. I need a way to catch exceptions of a different type. This is a real need in light of the new found usage for try/catch given generators. I've looked around and found one possible solution using catch guards ( http://wiki.ecmascript.org/doku.php?id=strawman:catch_guards ) , I know Firefox supports catch guards but I was unable to find anything in the specification or in the mailing list when searching relating to it. Petka added: Without predicated catch clauses you would need to write something like this: ```js Promise.coroutine(function *(){ try{ let db = yield DBEngine.open(northwind); let result = yield db.query(SELECT name FROM users) return res; } catch (e) { if( e instanceof RejectionError ) { //code to handle exception in DB } else { throw e; } } }); ``` The manual rethrow can easily be forgotten to be written ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Try/catch conditional exceptions in light of generators
That's a good question. I try to discuss problems I run into. Developers, me included have found ways to minimize reliance on try/catch in synchronous operations using monadic maybies and checking values. It's very often in JavaScript that I want to handle exceptions that are related to I/O and/or external resources. In JavaScript these operations are almost always asynchronous. It's very common to handle the issue of asynchronously handling exceptions using the mechanism that is used to wrap the asynchronous operation. - If it's a callback people typically use the `(err,` first parameter convention. - If it's a promise people use a rejected callback, a common (but not the prettiest) example is `.fail` in jQuery. Both these options don't suppress things like syntax errors, reference errors etc. There are of course other ways to do asynchronous operations and I/O but more generally, mechanisms that go around the language error handling constructs do a pretty good job at this. Generators give me a new great way to do concurrency, they reduce code and increase readability. However - they bring me back to the try/catch of the language which does not make the distinction or allow me address the issue without wrapping the catch with more code. On Tue, Nov 5, 2013 at 5:04 PM, Domenic Denicola dome...@domenicdenicola.com wrote: I am curious what, if anything, about this problem has to do with asynchronicity? That seems to be a key part of your point, but I don't understand why you wouldn't phrase the problem entirely in terms of synchronous operations since nothing seems unique to async. On 5 Nov 2013, at 09:48, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: Traditionally, JavaScript code contains some sort of asynchronous logic either on the client side or on the server side. This makes the `try/catch` construct non-practical for many real use cases because it can not catch errors caused by callbacks and/or other asynchronous operations involved. This is why we have common idioms like the `(err,result)` of NodeJS callbacks or reject in promises implementations and so on. NodeJS also introduces domains which let you catch all errors that originated from a piece of code in a certain way. ES6 Generators recently implemented in NodeJS allow us to do concurrency using coroutines. This allows for very nice code that's very readable in certain cases. The async_functions proposal is also very interesting solving the problem without needing a runner for the generator. However, one issue arises from using generators for such concurrency. The current way try/catch works with generators does not give us a way to differentiate things like syntax errors from logic errors. Consider the following piece of code using Bluebird promises: ``` Promise.coroutine(function *(){ try{ let db = yield DBEngine.open(northwind); let result = yield db.query(SELECT name FROM users) return res; } catch (e){ //code to handle exception in DB } }); ``` Noticed the `ReferenceError`? Not obvious at first glance. A compile time tool _might_ find it but I may have a closure variable named `res`. This might even happen later when making changes. A catch-all does not do a good job here. What I'd want to do is to catch all exceptions that are _mine_. I need a way to catch exceptions of a different type. This is a real need in light of the new found usage for try/catch given generators. I've looked around and found one possible solution using catch guards ( http://wiki.ecmascript.org/doku.php?id=strawman:catch_guards ) , I know Firefox supports catch guards but I was unable to find anything in the specification or in the mailing list when searching relating to it. Petka added: Without predicated catch clauses you would need to write something like this: ```js Promise.coroutine(function *(){ try{ let db = yield DBEngine.open(northwind); let result = yield db.query(SELECT name FROM users) return res; } catch (e) { if( e instanceof RejectionError ) { //code to handle exception in DB } else { throw e; } } }); ``` The manual rethrow can easily be forgotten to be written ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Protocol library as alternative to refinements (Russell Leggett)
Russell, thanks for the reply, it clarified a lot. I just wanted to mention that I did not bring up C# extension methods to suggest this behavior for protocols but just to illustrate how a different system for addressing a similar problem (in a different environment) does it. I do not think Protocols should behave this way :) On Tue, Oct 22, 2013 at 9:13 AM, Russell Leggett russell.legg...@gmail.com wrote: I don't like thinking of reading from the prototype (as in the case of fetching a method) any differently from reading from the own object. After all sharing functionality is at the very core of prototypical inheritance. Yeah, I'm not exactly married to it, but I liked the idea of being able to override at the instance level, therefore giving own properties highest priority. I think there is a very specific problem Protocols attempt to solve. I think that problem is sharing and adding functionality to a type in a scoped manner. Our other mechanisms for sharing functionality, prototypical inheritance and mixins do not scope well. What protocols give us is the ability to share functionality without having to modify the object. I think the syntax is also really nice and clever. (so far I'm not saying anything new) The way method resolution on the object itself works right now in protocols sounds pretty complicated though. What if we make it a part of the protocol instead? What if protocols had a way to define preferring the object implementation? Don't we already have that in Protocols? MyProtocol.extend(Array, {map:Array.prototype.map}); // sorry if that's incorrect syntax Doesn't this let me define that when encountering an array I prefer its own implementation over the protocol's? What does it really cost us to drop checking the object and its prototype rather than using the protocol method always? If anything, I'd use the object own properties and prototype chain as a last fallback after protocol options have been exhausted. I don't really see an obvious use case where I want to polymorphically prefer the object implementations over the protocols and if I do, I can just use Protocol.extend to specify that in that case. The only other thing that bothers me in the spec is that you specify by classes which sounds a bit problematic to me (I don't see an obvious behavioral way though (how do I say Array like?), and having a default implementation kind of addresses that). On Tue, Oct 22, 2013 at 5:35 PM, Dean Landolt d...@deanlandolt.com wrote: I think the idea of overriding at the instance level is appealing too, but doesn't dispatching on a string key open the door to the kinds of naming conflicts the concept so elegantly solves otherwise? I agree that arr.map is questionable for protocol walking, but it's just as questionable on the instance because of possible name conflicts! What naming conflicts do you see here? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Protocol library as alternative to refinements (Russell Leggett)
Dean Landolt d...@deanlandolt.com wrote: Say you have an object for which you want to implement the Cowboy and Canvas protocols (to borrow /be's favorite example). Both implement a draw method, but when you try to import from both protocols you'll naturally have to rename one or both. Now say you want to override Cowboy's `draw` method on an instance? You'll end up clobbering the Canvas protocol's draw method with the obviously wrong function. Not cool. This can be easily corrected with Symbols. I'm not sure I understand the example. What does a Cowboy's draw method do? Is it a specification of the Canvas protocol draw ? (In that case `.extend`ing the protocol seems to solve it). If you have a more concrete use case that would really help. I don't see how this is any different from other variables and general naming conflict issues when destructuring. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Protocol library as alternative to refinements (Russell Leggett)
On Tue, Oct 22, 2013 at 8:10 PM, Russell Leggett russell.legg...@gmail.com wrote: Revised algorithm: 1. If receiver has protocol method symbol as a property, use that as override. 2. Try to use protocol methods - start by checking receiver type mapping, then check up type hierarchy for any matches, and finally if no matches, use the default if defined. 3. Finally, if no matches and no default, check prototype for method of same name. Does that sound better? Much :) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
Hey everyone. I've talked to about 100 developers whose primary language is JS this last week (although I admit it was not a balanced survey, mainly people I know). Most of them (Over 80) do not feel that the problem I've mentioned before in scoped method extensions is a real problem they have to solve. The main argument was that polyfilling (and as Brendan put it prollyfilling) was good enough when not writing a library. I am now convinced that he syntax overhead makes it not worth it in JavaScript. I don't know how talking to developers works here or how it is weighted, but I think it gave me a pretty good indication. Thanks a lot for this discussion, I've learned a lot. Sorry if I wasted someone's time. Benjamin Gruenbaum. 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
Re: Protocol library as alternative to refinements (Russell Leggett)
Russell Leggett russell.legg...@gmail.com wrote: https://gist.github.com/genericallyloud/7086380 Very interesting. // 4. use the default if available what's the default in #4? The protocol's default? What's the behavior if no matching method is found? Also, can anyone explain why this solves the performance problem scoped object extensions have? It still seems like it would have to check the environment for protocols and then check the methods on all available protocols and do type matching to the type of the method. `Collections.extend(Array)` seems awfully similar to an array extensions, how does the `::` operator resolve the need for expensive lookup, can you explain that to me? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Protocol library as alternative to refinements (Russell Leggett)
Great, thanks for the clarifications. A few more scenarios: - Case 1: I have an object O of type Foo. A protocol P. - O has the structure {x:5,foo:7}; - The protocol implements `foo` but does not specifically for Foo (via .defaults). What happens? Does `P.foo` get invoked, or do we get an error because `O.foo` is not a function? Case 2: I have an object O of type Foo, Foo.prototype = new Bar. A protocol P. - O has the structure {x:5,foo:7}; - The protocol implements `foo` for Bar specifically (but not for Foo) What happens? (Similar to case above?) Case 3: I have an object O of type Foo, Foo.prototype = new Bar. A protocol P. - O has the structure {x:5,y:7}; - Bar has a method foo - The protocol implements `foo` for Bar specifically (but not for Foo) What happens? Does it invoke Bar.foo or P.foo? Case 4: I have an object O of type Foo, Foo.prototype = new Bar. A protocol P. - O has the structure {x:5,y:7}; - Bar has a method foo - The protocol implements `foo` for Bar specifically (but not for Foo) What happens? Does it invoke Bar.foo or P.foo ? Case 5: I have an object O of type Foo, I import two `Protocol`s that implement a method `Foo` at the same specificity level - what happens? Thanks On Mon, Oct 21, 2013 at 10:35 PM, Russell Leggett russell.legg...@gmail.com wrote: On Mon, Oct 21, 2013 at 3:17 PM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: Russell Leggett russell.legg...@gmail.com wrote: https://gist.github.com/genericallyloud/7086380 Very interesting. // 4. use the default if available what's the default in #4? The protocol's default? What's the behavior if no matching method is found? The default is something I go into in a little bit of detail further down: Collections.defaults({ each(iterator, context){ if (this.length === +this.length) { for (var i = 0, length = this.length; i length; i++) { //notice we also get to use :: for a simple call replacement if (context::iterator(this[i], i, this) === breaker) return; } } else { var keys = this.keys(); for (var i = 0, length = keys.length; i length; i++) { if (context::iterator(this[keys[i]], this[i], this) === breaker) return; } } }, This is defining a sort of default implementation of the method for the protocol, meaning that other types do not have to implement it in their own type specific implementation of the protocol. Also, can anyone explain why this solves the performance problem scoped object extensions have? It still seems like it would have to check the environment for protocols and then check the methods on all available protocols and do type matching to the type of the method. `Collections.extend(Array)` seems awfully similar to an array extensions, how does the `::` operator resolve the need for expensive lookup, can you explain that to me? Yes, the reason is because no new scopes or environments have been created. The protocol and its methods are simply variables - objects like anything else. Getting a protocol's method is not really any different from: import {map} from 'UnderscOOre'; //basically the same as let {map} = Array.prototype; //this is effectively the same whether you got it from the protocol or the function //pulled off of Array.prototype arr::map( x = x+2); The magic is what happens one of these protocol methods. The simplest to understand/naive approach to this would basically be that inside of a protocol, for each protocol method, you hold all the methods in a map going from type to implementation. The actual method used would inspect the |this| and follow the algorithm and use the maps to figure out which implementation to use. This would have a penalty - but it would be limited to the protocol method calls. Scoped extension would apply a penalty to *all* function calls everywhere. If protocols were natively supported, or at least some kind of hook for single dispatch on type, I'm pretty sure you could get function calls that were *at least* as fast as normal prototype based methods. Even if you didn't get native support, I have a feeling that something more clever than the naive approach could be used to hit the sweet spot and get some polymorphic inline caching, but maybe not. - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: Promises and Decidability in Asynchronous Error Handling
I don't think that's the same thing at all. Detecting an infinite loop is _extremely_ hard at most cases (and of course impossible at others. However instead of discussing the halting problem, I think what's bothering this guy is that `.then` does not throw an error when an error occurs within it even if that error is completely unhandled by the promise flow. Different libraries that implement promises handle errors differently. For example bluebird[0] writes the stack trace to stderr (or console.error) if the rejection is unhandled by the start of the second turn. I quote: your quote doesn't work as expected and you open console and see a stack trace : nice. On that topic, I'd appreciate some reading on promises being added to the spec of the language (since when does the ES language spec even deal with concurrency? I thought that was a part of the host environment. [0]: https://github.com/petkaantonov/bluebird#error-handling Domenic Denicola dome...@domenicdenicola.com wrote A well-known problem with loops, as implemented in various programming languages, is that infinite loops are silenced by default. Consider the following program, which simply adds some numbers in a loop: ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Protocol library as alternative to refinements (Russell Leggett)
On Tue, Oct 22, 2013 at 12:15 AM, Russell Leggett russell.legg...@gmail.com wrote: I'll preface this by saying that I haven't made a formal proposal and this isn't an actual library. You're doing a good job of spotting some undefined behavior which would probably be better defined by trying it out. I'll give my opinions on them, but it could all use a good test drive before coming down on these. This is exactly what I'm trying to do, figuring out how it acts in different scenarios. I know better solutions come from actual usage but at least I want to understand a behavior we can built from. I like this idea and it seems like something that can solve issues I have when coding. I can see most of your examples involve the interaction between the protocol method and a method supplied on the object itself... They definitely complicate things... I guess I would say that I would have this throw an error. ... Skipping foo on the object because its not a function seems too magical. Skipping `foo` on the object because it is not a function is too magical in my opinion too. Working out how instance methods work in this scenario seems like quite the task to me. The step of putting the protocol _between_ the object and the prototype sounds pretty hard to get right in particular. I don't like thinking of reading from the prototype (as in the case of fetching a method) any differently from reading from the own object. After all sharing functionality is at the very core of prototypical inheritance. Case 3: Ah, yes, I had thought about this a bit, but it had never made it into my gist at all. Let me revise my algorithm: 4. true - use Bar.foo This makes some sense. About scope resolution more generally I just want to make a note that in C# extension methods, the extension method is always the _last_ candidate. It would check anywhere in the inheritance chain _before_ attempting to evaluate the extension method. For example: ``` public class Bar { public int GetFive() { return 5;} } public class Foo : Bar{} public static class FooExt { static int GetFive(this Foo bar) { return ; } static string ToString(this Foo bar) { return Hi; } } static void Main(string[] args) { Console.WriteLine((new Foo()).GetFive()); // this prints 5 Console.WriteLine(new Foo())); // Uses the implementation of Object.ToString . } ``` This is a major difference between this proposal and C# extension methods. However, I'm not sure it's bad. Would you mind making an argumnt for prioritizing the protocol method over an object method? I have an object O of type Foo, I import two `Protocol`s that implement a method `Foo` at the same specificity level - what happens? This is an easy one and comes down to the benefits of making use of normal variables and lexical scoping. Remember that protocols don't affect the types at all, and the protocols exist completely independently of each other. Beautiful. This bit works out quite nicely. On Tue, Oct 22, 2013 at 12:15 AM, Russell Leggett russell.legg...@gmail.com wrote: I'll preface this by saying that I haven't made a formal proposal and this isn't an actual library. You're doing a good job of spotting some undefined behavior which would probably be better defined by trying it out. I'll give my opinions on them, but it could all use a good test drive before coming down on these. To help the discussion I'll paste the basic algorithm I outlined: 1. if the receiver has an own property of the same name, use that 2. if the receiver's type matches an extension of the protocol, use the protocol method 3. if the receiver has a method of the same name somewhere up the prototype chain, use that 4. use the default if available - Case 1: I have an object O of type Foo. A protocol P. - O has the structure {x:5,foo:7}; - The protocol implements `foo` but does not specifically for Foo (via .defaults). What happens? Does `P.foo` get invoked, or do we get an error because `O.foo` is not a function? I can see most of your examples involve the interaction between the protocol method and a method supplied on the object itself. Clojure protocols don't have this type of interaction. I tossed them in because they seemed like they would work well with some of the examples brought up in the other thread. They definitely complicate things... I guess I would say that I would have this throw an error. Logically to me, either the an error should be thrown because it would try to invoke foo on the object, or we should give up on the idea of falling back on the object. Skipping foo on the object because its not a function seems too magical. So here, O has an own property, so #1 and blows up Case 2: I have an object O of type Foo, Foo.prototype = new Bar. A protocol P. - O has the structure
Re: `String.prototype.symbolAt()` (improved `String.prototype.charAt()`)
I also noticed the naming similarity to ES6 `Symbol`s. I've seen people fill `String.prototype.getFullChar` before and similarly things like `String.prototype.fromFullCharCode` for dealing with surrogates before. I like `String.prototype.signAt` but I haven't seen it used before. I'm eager to hear what Allen has to say about this given his work on unicode in ecmascript. Especially how it settles with this http://wiki.ecmascript.org/doku.php?id=strawman:support_full_unicode_in_stringsrev=1304034700 I also think that this is important enough to be there. -- Forwarded message -- From: Mathias Bynens math...@qiwi.be To: Rick Waldron waldron.r...@gmail.com Cc: es-discuss@mozilla.org list es-discuss@mozilla.org Date: Fri, 18 Oct 2013 09:47:21 -0500 Subject: Re: `String.prototype.symbolAt()` (improved `String.prototype.charAt()`) On 18 Oct 2013, at 09:21, Rick Waldron waldron.r...@gmail.com wrote: I think the idea is good, but the name may be confusing with regard to Symbols (maybe not?) Yeah, I thought about that, but couldn’t figure out a better name. “Glyph” or “Grapheme” wouldn’t be accurate. Any suggestions? Anyway, if everyone agrees this is a good idea I’ll get started on fleshing out a proposal. We can then use this thread to bikeshed about the name. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Should String.prototype.split accept variable arguments optionally?
Splitting by one value or another seems to be a pretty common use case if Stack Overflow questions and personal experience are an indication. For example - and and /. Currently, the solution is to pass a regular expression to String.prototype.split . However, it would be nice to be able to pass variable arguments to the method. So if I want to split strings like 0-12-12 and 321+32/14 or TI-CK ER instead of having to do: ``` myString.split(/ |-|\/|\+/g); // this is no fun to read myString.split( ,-,/,+); // this is easier myString.split([ ,-,/,+]); // this is also easier. ``` The advantage of the second one (accepting an Array) is that it does not require additional handling of the second limit parameter. A possible advantage of the first one is that it's simpler. The algorithm for the second one could be quite simple, in 21.1.3.17 only _SplitMatch_ needs to be updated, and implementation sounds pretty simple in engines and the semantics simple in the spec. Some other languages: - C# accepts an array of `char` or array of string in its Split, http://msdn.microsoft.com/en-us/library/tabh47cf.aspx - Ruby doesn't do this with `.split`, behaves like JS http://ruby-doc.org/core-2.0.0/String.html#method-i-split - Java String.split only accepts a regex - Python doesn't do this with `.split` Advantages: - Nice api addition that solves a common use case. - A way to split by multiple delimiters easily without knowledge of regular expressions. - Does not break the existing API, especially if we use array syntax. Disadvantages - Extra overhead - Use case needs assertion (Reminds me of stuff in string_extras http://wiki.ecmascript.org/doku.php?id=harmony:string_extras ) What do you think? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Should String.prototype.split accept variable arguments optionally?
On Wed, Oct 16, 2013 at 7:15 PM, Rick Waldron waldron.r...@gmail.com wrote: This is subjective, as I have no trouble reading and understanding what this means and is expected to do (also subjective). Of course, this is another way to do it that does not require knowing regular expressions. I have no doubt that being easier/harder is subjective here. Since I've never actually found this to be a hardship, I'd be interested in reading through the SO postings you mentioned above. I don't keep a list :) Here is a bunch I just found: - http://stackoverflow.com/q/650022/1348195 - http://stackoverflow.com/q/12504216/1348195 - http://stackoverflow.com/questions/13867182/how-split-a-string-in-jquery-with-multiple-strings-as-separator?lq=1 - http://stackoverflow.com/questions/19313541/split-a-string-based-on-multiple-delimiters?lq=1 - http://stackoverflow.com/q/4168644/1348195 - http://stackoverflow.com/questions/9535203/split-string-by-whitespace-and-dashes This is a _very_ shallow search, lots of the ones I run into are closed as duplicates refering to the one with the many upvotes above. _Personally_ I have no problem with regular expressions but many find them confusing in such cases (I admit, a lot of those are language newbies I run into in JS chats like that on Stack Overflow that just want JS to do something - but they're a user base too). On Wed, Oct 16, 2013 at 7:15 PM, Rick Waldron waldron.r...@gmail.comwrote: On Wed, Oct 16, 2013 at 8:54 AM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: Splitting by one value or another seems to be a pretty common use case if Stack Overflow questions and personal experience are an indication. For example - and and /. Currently, the solution is to pass a regular expression to String.prototype.split . However, it would be nice to be able to pass variable arguments to the method. So if I want to split strings like 0-12-12 and 321+32/14 or TI-CK ER instead of having to do: ``` myString.split(/ |-|\/|\+/g); // this is no fun to read This is subjective, as I have no trouble reading and understanding what this means and is expected to do (also subjective). myString.split( ,-,/,+); // this is easier myString.split([ ,-,/,+]); // this is also easier. ``` The advantage of the second one (accepting an Array) is that it does not require additional handling of the second limit parameter. A possible advantage of the first one is that it's simpler. The algorithm for the second one could be quite simple, in 21.1.3.17 only _SplitMatch_ needs to be updated, and implementation sounds pretty simple in engines and the semantics simple in the spec. Some other languages: - C# accepts an array of `char` or array of string in its Split, http://msdn.microsoft.com/en-us/library/tabh47cf.aspx - Ruby doesn't do this with `.split`, behaves like JS http://ruby-doc.org/core-2.0.0/String.html#method-i-split - Java String.split only accepts a regex - Python doesn't do this with `.split` Advantages: - Nice api addition that solves a common use case. - A way to split by multiple delimiters easily without knowledge of regular expressions. - Does not break the existing API, especially if we use array syntax. Disadvantages - Extra overhead - Use case needs assertion (Reminds me of stuff in string_extras http://wiki.ecmascript.org/doku.php?id=harmony:string_extras ) What do you think? Since I've never actually found this to be a hardship, I'd be interested in reading through the SO postings you mentioned above. Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Should String.prototype.split accept variable arguments optionally?
On Wed, Oct 16, 2013 at 8:18 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: also, this is the same: `myString.split(/[ -/+]/)` Yes, that's true, not sure how that works for multi character delimiters. maybe it's better to explain those users that knowing RegExp might bring benefits for their purpose (coding) ? This is not the first or last thing in a language that is intended to make life easier for users who are not highly trained professionals. I agree that the added value is not huge here, but implementation is pretty inexpensive and I can see people use this. On Wed, Oct 16, 2013 at 8:18 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: also, this is the same: `myString.split(/[ -/+]/)` maybe it's better to explain those users that knowing RegExp might bring benefits for their purpose (coding) ? On Wed, Oct 16, 2013 at 10:14 AM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: I stopped here On Wed, Oct 16, 2013 at 5:54 AM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: ``` myString.split(/ |-|\/|\+/g); // this is no fun to read myString.split( ,-,/,+); // this is easier myString.split([ ,-,/,+]); // this is also easier. ``` easier for who ? All I was doing is being sure no double quoting was missing or not escaped correctly ... also you don't need the g flag and RegExp is much more powerful than multiple strings `myString.split(/before(and|or)?after/);` instead of 3 partially repeated nonsense ? My 2 cents ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Should String.prototype.split accept variable arguments optionally?
On Wed, Oct 16, 2013 at 9:03 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: How could change 12+ years of legacy be considered inexpensive ? This proposal does not break anything, the only thing that will/might work differently is people passing an array to .split right now and expecting something like splitting on `firstElem,secondElem...`. Current usages of .`split` with a string or with a regular expression will continue to function exactly the same, the only thing happening here is adding an overload for an array. Non highly trained professionals should be simple things or try to learn something new that won't hurt... so please make it simpler If we can make life the easier without breaking anything, why not? A lot of people use JavaScript on the web in practice for making websites dynamic, most of those people are not me and certainly not you but they're still probably the majority. How many so called jQuery programmers are there? I'm not sure taking a common use case like `.split` on multiple delimiters and removing a skill (Regular Expressions) they had to know before in order to write code they understand and by that making the language more accessible to them is not a good idea. There are and have been such API changes in the language. Why have `str.contains` if you can just do `~str.indexOf`. Why have `.startsWith`, or `.indexOf` on arrays? I'm not saying we _should_ add a `.split` third overload in addition to the already existing two. I do however think it is an interesting idea that in practice a lot of developers, especially ones who do not remember the abstract comparison algorithm by heart can possibly benefit from. Are you against changes like `.contains` or `.startsWith` too? What do you think is the criterea for such additions to the language? On Wed, Oct 16, 2013 at 9:21 PM, Brendan Eich bren...@mozilla.com wrote: It's hard to add extra optional arguments to a long-standing built-in. People write code that passes an extra arg that has been ignored till the change; browsers that try shipping the new version then break that content, user blames browser (rightly so) but also the page, sometimes (not right). Agreed. Even without compatibility issues, I get confused questions from students regarding the behavior of methods changing behavior based on number of arguments (`Array` for example) way more often than I'd expect. (and props on the spec, being able to send students there in such cases is extremely enabling imo and a great exercise on its own). What about the version with the overload accepting an Array instead? It seems more backwards compatible than the varargs version. Regexps suck away oxygen too, as others note. My suggestion is to focus fire for greater effect. If we need a new variable-split, we want a new API. I actually like the existing API for the most part and just wish it made life easier at times. Especially for learners. I'd like to teach my nephew JavaScript as a first language and I don't want to go anywhere near regular expressions. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Should String.prototype.split accept variable arguments optionally?
On Wed, Oct 16, 2013 at 11:46 PM, Rick Waldron waldron.r...@gmail.com wrote: What about the version with the overload accepting an Array instead? It seems more backwards compatible than the varargs version. I meant the version accepting an array `.split([a,b,c])` rather than `.split(a,b,c)` but the 12 years and the two lightly arguments by Andrea and Brendan convinced me that adding something like this to .split() is too risky. in the future, tell students to construct new Arrays of numbers (that may have 1 entry) with Array.of(): Nice! I've almost never had to do Array(..items), usually I just suggest a literal in the cases they do :) Thanks for the tip though, I should really read the ES6 current spec from start to end. On Wed, Oct 16, 2013 at 11:46 PM, Rick Waldron waldron.r...@gmail.comwrote: On Wed, Oct 16, 2013 at 4:25 PM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: On Wed, Oct 16, 2013 at 9:03 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: How could change 12+ years of legacy be considered inexpensive ? This proposal does not break anything, the only thing that will/might work differently is people passing an array to .split right now and expecting something like splitting on `firstElem,secondElem...`. Current usages of .`split` with a string or with a regular expression will continue to function exactly the same, the only thing happening here is adding an overload for an array. Non highly trained professionals should be simple things or try to learn something new that won't hurt... so please make it simpler If we can make life the easier without breaking anything, why not? A lot of people use JavaScript on the web in practice for making websites dynamic, most of those people are not me and certainly not you but they're still probably the majority. How many so called jQuery programmers are there? As one of jQuery's own representatives to Ecma/TC39, I still stand by my original response. After reading through those links, I agree with Andrea: it's a handful of people that just need time and motivation to learn. I'm not sure taking a common use case like `.split` on multiple delimiters and removing a skill (Regular Expressions) they had to know before in order to write code they understand and by that making the language more accessible to them is not a good idea. There are and have been such API changes in the language. Why have `str.contains` if you can just do `~str.indexOf`. Why have `.startsWith`, or `.indexOf` on arrays? I'm not saying we _should_ add a `.split` third overload in addition to the already existing two. I do however think it is an interesting idea that in practice a lot of developers, especially ones who do not remember the abstract comparison algorithm by heart can possibly benefit from. Are you against changes like `.contains` or `.startsWith` too? What do you think is the criterea for such additions to the language? I'm all for new additions, but nothing is free and changing an existing thing is potentially even more expensive. Brendan's response is the most compelling. On Wed, Oct 16, 2013 at 9:21 PM, Brendan Eich bren...@mozilla.com wrote: It's hard to add extra optional arguments to a long-standing built-in. People write code that passes an extra arg that has been ignored till the change; browsers that try shipping the new version then break that content, user blames browser (rightly so) but also the page, sometimes (not right). Agreed. Even without compatibility issues, I get confused questions from students regarding the behavior of methods changing behavior based on number of arguments (`Array` for example) way more often than I'd expect. (and props on the spec, being able to send students there in such cases is extremely enabling imo and a great exercise on its own). Too late to change Array arg handling. In the future, tell students to construct new Arrays of numbers (that may have 1 entry) with Array.of(): Array.of(42).length === 1; (vs. Array(42).length === 42; ) What about the version with the overload accepting an Array instead? It seems more backwards compatible than the varargs version. What version is that? Regexps suck away oxygen too, as others note. My suggestion is to focus fire for greater effect. If we need a new variable-split, we want a new API. I actually like the existing API for the most part and just wish it made life easier at times. Especially for learners. I'd like to teach my nephew JavaScript as a first language and I don't want to go anywhere near regular expressions. Again, this is too subjective. Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
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: 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
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
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
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: 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: 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
Re: Scoped binding of a method to an object
On Mon, Oct 14, 2013 at 6:44 PM, Brendan Eich bren...@mozilla.com wrote: So, see the http://scg.unibe.ch/archive/**papers/Berg03aClassboxes.pdfhttp://scg.unibe.ch/archive/papers/Berg03aClassboxes.pdf work, which inspired Ruby refinements as well as the scoped object extensions strawman, and try to come up with compile-time-complete resolution. Wait a minute, does this mean that the *major* blocking step in this proposal is the speed? Are we in agreement that given the performance issue is solved we: a) Want this sort of feature/ability in the language with the extra syntax it entails at all? b) Want it enough to ask browser vendors actually implement it in their JS engines? c) Want it enough to actually write down a clear scope resolution algorithm that decdes when to choose extension methods? Because I thought that the problem you've had with it is that it creates more confusing scoping *to the user.* On Mon, Oct 14, 2013 at 6:44 PM, Brendan Eich bren...@mozilla.com wrote: Till Schneidereit mailto:till@tillschneidereit.**nett...@tillschneidereit.net October 13, 2013 2:39 PM On Sun, Oct 13, 2013 at 8:40 PM, Brendan Eichbren...@mozilla.com wrote: Till Schneidereitmailto:till@**tillschneidereit.nett...@tillschneidereit.net October 13, 2013 11:28 AM And now it causes problem for TC39, browser vendors, sites that use it and end users. (The last group should be affected the least because the first three groups work together to prevent it, of course.) I think we agree. My point was that the objections are not definitive, not axiomatic enough. The costs are born later and by others. This is a recipe for social ills. Ok, we do agree, then. This kind of problem is also part of life as we know it, in many domains. I don't have a general solution :-). What we do about it is up to us, but just asserting that developers should stop extending primordials sounds like King Canute to me. Also agreed. It's still not entirely obvious to me what exactly we should do about it, sadly. And not only now, but going forward. Cow path paving requires the cows' ability to trod on the same ground that might be paved later. That very fact means that the cow paths might end up colliding with paved streets. Have you ever driven in town in Boston, Massachusetts, USA? :-P I don't see how this basic conundrum can be resolved without a scope based resolution-mechanism (no pun intended). If namespaces and scoped object extensions have fallen, what is left? I agree with Andreas Rossberg, who just wrote My take-away was that scoped extension methods are only bearable in a language with a static, nominal class system (like C#), where the additional lookup dimension can be resolved at compile time. So, see the http://scg.unibe.ch/archive/**papers/Berg03aClassboxes.pdfhttp://scg.unibe.ch/archive/papers/Berg03aClassboxes.pdfwork, which inspired Ruby refinements as well as the scoped object extensions strawman, and try to come up with compile-time-complete resolution. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Readdition of __proto__
Let me start by apologizing for adding noise to the list. I looked for discussion of the standardization of __proto__ in the ES6 spec and couldn't find any. This is probably my shortcoming but I didn't know where to look or how to search the mailing list. I found a lot of threads discussing possible problems with Object.create(null) and __proto__ but not the discussion and decision to include it in the spec and to tell browser vendors to implement it. And then Branden's famous reply where he says he thinks it's a horrible idea :) Frankly, when I heard a while back it was introduced it surprised me (why would objects suddenly change their prototype?) I'm really interested in hearing the arguments and counter-arguments for/against it. Thanks again and sorry. Benjamin Gruenabum. ___ 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 had a problem articulating my thoughts in this last one. I was trying *not* to tie my cart in front of the horse. Even before worrying about implementer performance issues which sound important I wanted to know if: The problem I had was a real problem to other developers too and it was a big enough problem for people to care about. I'll gladly try and possibly fail in coming up with a coherent and contained design. I wasn't looking for a solution yet, (and there are probably people here with more clever solutions - but I'll gladly give it my shot) at this stage I'm merely trying to assert if scoped extension methods solve a real problem people have in JavaScript. I said implementors objected. How did you miss that? I didn't. I read everything you and other people wrote about it - It was an interesting read too. I'm just not convinced that it's _the_ blocking issue yet. 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. 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. On Mon, Oct 14, 2013 at 10:55 PM, Brendan Eich bren...@mozilla.com wrote: Benjamin (Inglor) Gruenbaum mailto:ing...@gmail.com October 14, 2013 12:37 PM On Mon, Oct 14, 2013 at 6:44 PM, Brendan Eich bren...@mozilla.commailto: bren...@mozilla.com wrote: So, see the http://scg.unibe.ch/archive/**papers/Berg03aClassboxes.pdfhttp://scg.unibe.ch/archive/papers/Berg03aClassboxes.pdfwork, which inspired Ruby refinements as well as the scoped object extensions strawman, and try to come up with compile-time-complete resolution. Wait a minute, does this mean that the /major/ blocking step in this proposal is the speed? Not just the performance hit, also the complexity, as Andreas and I independently wrote. Extra parameters refract through internal APIs, they impose not only speed costs but also bug habitat and unwanted degrees of freedom in general. They cost. A compile-time solution will require something new, syntax and semantics, to confine the complexity. Do that, and then let's talk. Are we in agreement that given the performance issue is solved we: a) Want this sort of feature/ability in the language with the extra syntax it entails at all? Andreas also reminded me that the strawman had semantic design issues too. We can dredge those up if need be, but I think not yet. Not everyone wants this in some single, well-designed sense that merely imposes a speed reduction when used. Again, the complexity hits all paths in engines. The slow paths could be reoptimized but the hit is to the entire object model, not just in certain lexical scopes but via the heap, in all objects. b) Want it enough to ask browser vendors actually implement it in their JS engines? Again, there is no well-specified it yet. c) Want it enough to actually write down a clear scope resolution algorithm that decdes when to choose extension methods? Aha, here is the horse that goes in front of the cart. Do this first, call it step (a), worry about (b) and (c) later. Thus your wait a minute does not make sense. We're waiting for a coherent and contained design, one that doesn't hit object model and engine perf all over the map, and one that hangs together on its own. Because I thought that the problem you've had with it is that it creates more confusing scoping /to the user./ I said implementors objected. How did you miss that? But there were design issues too. And in general, as we discovered with the 'private foo;' part of the original private names proposal, user confusion or complexity remains an objection. See my previous post. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Readdition of __proto__
Thanks. Found a bunch of interesting things. Hopefully I'll find some use case where it doesn't completely break the beautiful OOP behavioral typing gives us when we play nice with it (Yep, that dog of yours, he's no longer an animal) :) On Mon, Oct 14, 2013 at 11:10 PM, Brendan Eich bren...@mozilla.com wrote: To search es-discuss, I use site:mail.mozilla.org es-discuss as first two terms in a Google search. Sometimes I just use es-discuss. If you add __proto__ you'll find lots to read. Add meeting notes and you'll find recorded TC39 decisions. I usually find links and include them here to avoid just saying do your own search, but I'm short on time, sorry! /be Benjamin (Inglor) Gruenbaum mailto:ing...@gmail.com October 14, 2013 12:51 PM Let me start by apologizing for adding noise to the list. I looked for discussion of the standardization of __proto__ in the ES6 spec and couldn't find any. This is probably my shortcoming but I didn't know where to look or how to search the mailing list. I found a lot of threads discussing possible problems with Object.create(null) and __proto__ but not the discussion and decision to include it in the spec and to tell browser vendors to implement it. And then Branden's famous reply where he says he thinks it's a horrible idea :) Frankly, when I heard a while back it was introduced it surprised me (why would objects suddenly change their prototype?) I'm really interested in hearing the arguments and counter-arguments for/against it. Thanks again and sorry. Benjamin Gruenabum. __**_ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Readdition of __proto__
but it should be a quick shortcut to create inheritance too such `var obj = {__proto__: null}` keeping compatibility but avoiding troubles with `JSON` serialized objects where once again `{__proto__:[]}` will behave as named property instead of prototype mutator. I hope these answers are OK and to all others, please correct me whenever you think whatever I've written is wrong. Best Regards, Andrea Giammarchi On Mon, Oct 14, 2013 at 12:51 PM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: Let me start by apologizing for adding noise to the list. I looked for discussion of the standardization of __proto__ in the ES6 spec and couldn't find any. This is probably my shortcoming but I didn't know where to look or how to search the mailing list. I found a lot of threads discussing possible problems with Object.create(null) and __proto__ but not the discussion and decision to include it in the spec and to tell browser vendors to implement it. And then Branden's famous reply where he says he thinks it's a horrible idea :) Frankly, when I heard a while back it was introduced it surprised me (why would objects suddenly change their prototype?) I'm really interested in hearing the arguments and counter-arguments for/against it. Thanks again and sorry. Benjamin Gruenabum. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Scoped binding of a method to an object
Scoped binding of a method to an object Well, I know how some languages solve this issue but I wondered if ECMAScript considered addressing this or already have and I missed it. Often, I want to extend objects, for example - Array.prototype.shuffle - takes an array and shuffles it. However, this is considered bad practice for many reasons I don't have to repeat here (what if other libraries also override it? What if some user code? What if it makes it to the standard some day?) The problem is even more prevalent in stuff like String.prototype.contains which we know will be in the next spec - people had little way to add that function to the string prototype *before* it was adapted to the spec and not get eventually bitten. Stuff like underscore _.shuffle makes for less object oriented code, I find it harder to write and it feels like the code is not where it belongs. What I'd like is a way to add such methods in a scoped way, so within *my* code I get to use .shuffle but any code that is not in that scoped block does not get access to this method. Has there been a proposal or discussion about this in the past? Benjamin Gruenabum ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
David Bruant bruan...@gmail.com wrote This proposal does not aim at solving the problem of library conflicts which existed before this proposal and should be solve independently. Of course, and I'm sorry if I implied otherwise. I'm sure we all acknowledge the problem of extending the native prototypes in libraries. I just don't understand how having a `_` prefix attempts to give us a solution to the problem. I'm not saying I have a solution either, but I think implying that it's ok to extend them with a prefix doesn't really solve much. Maybe I got what you were trying to say wrong though. On Sun, Oct 13, 2013 at 9:25 PM, David Bruant bruan...@gmail.com wrote: Le 13/10/2013 20:03, Benjamin (Inglor) Gruenbaum a écrit : David Bruant bruan...@gmail.com wrote: Concretely, attempted prolyfills, could be _-prefixed (that really fits with what you call poor-man's prefixing, I believe) Authors would feel free to add something like Array.prototype._shuffle or Array.prototype._last, or EventTarget.prototype._on without worrying about collision with the platform. What if I use two libraries that polyfill `_shuffle` or `_last` differently (let's say with different behavior for an empty array for `_last` or weaker guarantee on the randomness in `_shuffle`)? What do you do today when a library overrides Array.prototype.concat with a different semantics? What do you do when you load two libraries each defining a global $ with different semantics? Apply every prevention/resolution mechanism you use today with global properties. Among other ideas: * don't load libraries that are known to have conflicts (!!) * isolate the code that enhance built-ins (preferably, run it before anything else and not in the middle of your application lifecycle) * Define functions as non-configurable/non-writable in development mode to discover conflicts before pushing to production. This proposal does not aim at solving the problem of library conflicts which existed before this proposal and should be solve independently. 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
Prollyfilling is great too (perhaps you disagree?), and as its name suggests it happens *before* the method is added to the spec. So in your opinion adding a `.shuffle` method to an Array in a library I ship to users is a good idea if it makes my code clearer and nicer? I'm not saying I disagree, I'm not one of those people who passes an extra parameter for `undefined` in a function. I just think it can be very risky. When I have to work on big code bases that run JavaScript end to end using multiple frameworks and libraries on both sides, I find that extending object prototypes can be _very_ risky - and Prollyfilling (nice term by the way) has bitten me before. Sure, in _my_ code it can be very nice, but I expect libraries to have little to no side effects on my code and that's exactly the cases it can bite me. How exactly did that example fail? The differences in detail hardly matter; PrototypeJS trod a cow-path that ES5 paved. Most users don't worry about the edge case differences. I don't think anyone today is doubting the enormous contribution PrototypeJS had and `.bind` was very useful in it and is very useful in ES5. However, running into edge cases and getting unexpected results is something I don't think people appreciate. The SweetJS case is just as interesting. There is no doubt some of the most interesting API additions have come from people extending natives and that says something. However, today when rather than writing 1000 line pages I see more and more 100 thousand lines code bases using multiple libraries - side effects that extending natives sound _very_ scary, and being able to extend the natives in a way that does not bite me is something I'd _really_ love to play with. Don't worry about syntax yet. Of course, I was just toying around. Like I've said before, pretty much anyone else in this discussion is more qualified to come with an actual solution than me. This must cost, and it does cost. Would you mind elaborating on that or linking to relevant discussion about the last proposal? I'd love to understand the issues involved and get a better understanding of the challenges something like this would bring. On Sun, Oct 13, 2013 at 9:37 PM, Brendan Eich bren...@mozilla.com wrote: Benjamin (Inglor) Gruenbaum mailto:ing...@gmail.com October 13, 2013 11:00 AM Brendan Eichbren...@mozilla.com mailto:bren...@mozilla.com wrote: No, object detection, polyfilling, and even prollyfilling are common and successful adaptationsp on the Web. Polyfilling is great _after_ the method has already been added to the spec. Prollyfilling is great too (perhaps you disagree?), and as its name suggests it happens *before* the method is added to the spec. I'm completely fine with adding an Array.prototype.map shim to IE8, the problem with adding a method that's not on the prototype yet is that it'll fail in case the spec is different from the implementation I chose. If you mentioned PrototypeJS, its `.bind` method is one such example. How exactly did that example fail? The differences in detail hardly matter; PrototypeJS trod a cow-path that ES5 paved. Most users don't worry about the edge case differences. Your subject recalls a defunct proposal to add lexically-scoped but heap-based -- therefore object property-lookup performance hindering -- extension properties. I have to say this surprises me, a performance issue is the last thing I expected. What about attaching a prototype as a closure variable, something (and this is a syntax I __don't__ like) like: ``` (function(use Array){ Array.prototype.contains = function() { ... ... // any code here has access to .contains, code that did not originate here does not have such access, much like a closure. // other code is free to use Array without any collisions. })() ``` Again, I __don't__ like this sort of syntax and I'm __not__ sure about the semantics here, I just noticed I have this problem - I'm probably not the most qualified for coming up with the solution out of the amazing minds right here. Don't worry about syntax yet. The issue in any such semantic extension is the required extra lookup parameter: not just contains on the right of dot, but the enclosing closure scope. Unqualified identifiers (ones not used after dot) indeed require lookup via closure environments, to the global (let's ignore 'with' and DOM inline event handlers). Dot-qualified identifiers and equivalent bracketed computed property name accesses require prototype chain lookup. No matter the syntax, and independent of details of how one specs it, you're proposing a hybrid of the two schemes. This must cost, and it does cost. /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
As Brendan points out, doing this in a scoped way adds a third parameter representing the scope, or that somehow needs to be scope specific. Such a third parameter needs to be first class. WeakMaps and relationships do exactly that. My relative lack of experience here is probably working against me. Would you mind explaining how WeakMaps (and later relationships) give me that third scope parameter? Also, are you implying adding this sort of scoped extension of a native prototype be possible/easy once those features are implemented? (Sending me to reading is great too, I don't want to waste your time) On Sun, Oct 13, 2013 at 10:00 PM, Mark S. Miller erig...@google.com wrote: On Sun, Oct 13, 2013 at 11:36 AM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: First of all - well put. Thanks. Second, wouldn't being able to do this in a scoped way solve the conflict problem? As Brendan points out, doing this in a scoped way adds a third parameter representing the scope, or that somehow needs to be scope specific. Such a third parameter needs to be first class. WeakMaps and relationships do exactly that. On Sun, Oct 13, 2013 at 9:33 PM, Mark S. Miller erig...@google.comwrote: Any library that monkey patches primordials and wishes to be able to rely on the primordials being mutated only according to it should demand to be run before primordials are otherwise corrupted or frozen, and should freeze the primordials after patching. Of course, such a library isn't a library in the traditional sense -- it is a kernel for everything loaded into that realm after it. Two such kernels aren't composable because of this unsolvable conflict problem. Libraries meant to be composable should not mutate primordials, and should assume only that primordials are in some uncorrupted state. On Sun, Oct 13, 2013 at 11:25 AM, David Bruant bruan...@gmail.comwrote: Le 13/10/2013 20:03, Benjamin (Inglor) Gruenbaum a écrit : David Bruant bruan...@gmail.com wrote: Concretely, attempted prolyfills, could be _-prefixed (that really fits with what you call poor-man's prefixing, I believe) Authors would feel free to add something like Array.prototype._shuffle or Array.prototype._last, or EventTarget.prototype._on without worrying about collision with the platform. What if I use two libraries that polyfill `_shuffle` or `_last` differently (let's say with different behavior for an empty array for `_last` or weaker guarantee on the randomness in `_shuffle`)? What do you do today when a library overrides Array.prototype.concat with a different semantics? What do you do when you load two libraries each defining a global $ with different semantics? Apply every prevention/resolution mechanism you use today with global properties. Among other ideas: * don't load libraries that are known to have conflicts (!!) * isolate the code that enhance built-ins (preferably, run it before anything else and not in the middle of your application lifecycle) * Define functions as non-configurable/non-writable in development mode to discover conflicts before pushing to production. This proposal does not aim at solving the problem of library conflicts which existed before this proposal and should be solve independently. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Cheers, --MarkM -- 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
Thanks, this really helped me understand the underlying issue here forcing dynamic resolution of scope here. It sounds a lot harder than I initially thought I have to say the fact this is so deeply rooted in the language semantics is somewhat surprising to me. That said, I think I see why behavioral typing would be act like this and I expect this to still be a lot harder than I imagine. Here is a counterexample based on the strawman's syntax: ... When I pass a parameter `a` to a function and call `a.where` , whether or not it's an extension method - don't I still have to do dynamic scope resolution? Doesn't it still have to walk the prototype chain until I find `.where` - just like if I pass an array-like with `.splice` and send it to a method using it and it has to figure out it's not Array.prototype.splice? Off the top of my head - what about for the duration of the scope of these methods we have a prototype right after Array.prototype - in this scenario. Doesn't this make `c` go to Object.prototype.where and then String.prototype.select and all `b` does is another prototype chain look up before reaching the extension? This is probably another naive suggestion though. On Sun, Oct 13, 2013 at 10:15 PM, Brendan Eich bren...@mozilla.com wrote: Benjamin (Inglor) Gruenbaum mailto:ing...@gmail.com October 13, 2013 11:19 AM Keeping a third parameter beyond object and property name seems unnecessary. Here is a counterexample based on the strawman's syntax: // In module LINQ's body: extension Array.prototype { where: Array.prototype.filter, select: Array.prototype.map } export function query(a, w, s) { return a.where(w).select(s); } import {query} from LINQ; Array.prototype.select = () = oops; var b = readData(); var w = ..., s = ...; var r = query(b, w, s); // So far, so good. Now let's try an array-like: var c = { length: 0 }; // and let's be mean: Object.prototype.where = () = oops for real!; String.prototype.select = x = x; // identity function // Fill c from b and query c with w and s: b.forEach(e = c[c.length++] = e); var s = query(c, w, s); // This must hold: assertEqual(s, oops for real!); The only way to make this work is for the code in LINQ's body, in function query, to look for 'where' in 'a' (whose type is not known statically) by passing a token for the extended scope of module LINQ's body. When 'a.where' is evaluated to call the method, if 'a' is an instance of Array.prototype with no shadowing 'where', in particular when it refers to 'b', then the extension method = Array.prototype.filter is found. When 'a' refers to 'c', however, the code in LINQ does not know this _a priori_, so again the lookup of 'where' in c must pass the scope token. But this time, because c is an array-like Object instance that does not delegate to Array.prototype, the extension 'where' method is not found. In my likely naive eyes, dynamic `this` gives us great power here. Thinking about other languages that deal with the problem. As far as I remember C# extension methods are just (really nice) syntactic sugar for statics. C# has static types and name lookup rules. JS has neither in full, although its name lookup rules are static within functions (and blocks in ES6), excluding 'with'. Is it difficult to convert something like: ``` Array.prototype.last = function(){ return this[this.length-1] } ``` To something like ``` function Array$prototype$last(param1){ return (function(){ return this[this.length-1] }).call(param1); } ``` ? You have not defined convert, and there's no client code that calls 'last' on a given array instance. Another way of saying this: your name mangling does nothing to help an array ('b' in my example) find its method. There's no static type, no class or traits. The lookup in LINQ to call a.where is fully dynamic. Same for any use of your last method. The name rendezvous must be via prototypal lookup. If you wrote client code in scope of the 'last' extension, e.g. var b = [1, 2, 3]; alert(b.last()); and expected some whole-program transformation (which we do not perform in JS, too much ambiguity -- think of computed property names, never mind 'with' and the global object and eval!) that results in var b = [1, 2, 3]; alert((b instanceof Array) ? Array$prototype$last.call(b) : b.last()); then you have essentially added the third (scope token) parameter by code expansion. Whether ?: or an if statement or polymorphic lookup is used, that's real added runtime cost, and it won't fly. /be -- Forwarded message -- From: Erik Arvidsson erik.arvids...@gmail.com mailto: erik.arvidsson@gmail.**com erik.arvids...@gmail.com To: Brendan Eich bren...@mozilla.com mailto:bren...@mozilla.com Cc: es-discuss es-discuss@mozilla.org mailto:es-discuss@mozilla.org** Date: Sun, 13 Oct 2013 13:32:23 -0400 Subject: Re: Scoped binding of a method to an object
Re: Scoped binding of a method to an object
Function traits and mixins are the bread and butter of JS. Being able to share functionality is the pumping heart of prototypical inheritance, especially in a behaviorally typed environment. Much like a possible issue I have with what Rick suggested (although mixins and decoration are not the same) - let's say you have ` Enumerable_first_last.call(arr)` , and then I `.map` or `.filter` that mixed in array - the resulting array no longer has the trait. I can of course call Object.mixin on the result of `.map` and override `.map` on a Enumerable_first_last but that's a tedious process I don't want to have to do for every trait (what if I add several? Do I now have to keep track and compose?) It's an interesting suggestion and a common pattern, but I really hope we can do better. On Mon, Oct 14, 2013 at 12:01 AM, Peter Seliger peter.seli...@googlemail.com wrote: If you really have to live with those restriction you do describe, there still is a low level solution working since ES 3 that keeps the implemented codebase of certain behaviors at one place without effecting any other code - function based traits and mixins. One could e.g. write ones own implementations of an Enumerable's [first], [last] accessors. var Enumerable_first_last = (function () { var Trait, first = function () { return this[0]; }, last = function () { return this[this.length - 1]; } ; Trait = function () { this.first = first; this.last = last; }; return Trait; }()); From that point one is free to decide of where to apply that trait. var str = JavaScript natively supports Traits, arr = str.split( ), coll = { 0: foo, 1: bar, 2: baz, length: 2 } ; It is totally fine to apply additional behavior separately to objects that are in need of it. Enumerable_first_last.call(arr); arr.first(); // JavaScript arr.last(); // Traits Enumerable_first_last.call(coll); coll.first(); // foo coll.last(); // bar One also could delegate this behavior to an objects prototype. Enumerable_first_last.call(String.prototype); // works for all [[String]] implementations that do allow access via [idx] str.first(); // J str.last(); // s This approach in its first step decouples implementation from having it directly effecting a system. The second step is about responsibility and making decisions. Peter On Sun, Oct 13, 2013 at 8:47 PM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: Prollyfilling is great too (perhaps you disagree?), and as its name suggests it happens *before* the method is added to the spec. So in your opinion adding a `.shuffle` method to an Array in a library I ship to users is a good idea if it makes my code clearer and nicer? I'm not saying I disagree, I'm not one of those people who passes an extra parameter for `undefined` in a function. I just think it can be very risky. When I have to work on big code bases that run JavaScript end to end using multiple frameworks and libraries on both sides, I find that extending object prototypes can be _very_ risky - and Prollyfilling (nice term by the way) has bitten me before. Sure, in _my_ code it can be very nice, but I expect libraries to have little to no side effects on my code and that's exactly the cases it can bite me. How exactly did that example fail? The differences in detail hardly matter; PrototypeJS trod a cow-path that ES5 paved. Most users don't worry about the edge case differences. I don't think anyone today is doubting the enormous contribution PrototypeJS had and `.bind` was very useful in it and is very useful in ES5. However, running into edge cases and getting unexpected results is something I don't think people appreciate. The SweetJS case is just as interesting. There is no doubt some of the most interesting API additions have come from people extending natives and that says something. However, today when rather than writing 1000 line pages I see more and more 100 thousand lines code bases using multiple libraries - side effects that extending natives sound _very_ scary, and being able to extend the natives in a way that does not bite me is something I'd _really_ love to play with. Don't worry about syntax yet. Of course, I was just toying around. Like I've said before, pretty much anyone else in this discussion is more qualified to come with an actual solution than me. This must cost, and it does cost. Would you mind elaborating on that or linking to relevant discussion about the last proposal? I'd love to understand the issues involved and get a better understanding of the challenges something like this would bring. On Sun, Oct 13, 2013 at 9:37 PM, Brendan Eich bren...@mozilla.comwrote: Benjamin (Inglor) Gruenbaum mailto:ing...@gmail.com October 13, 2013 11:00 AM Brendan Eichbren...@mozilla.com mailto:bren...@mozilla.com wrote: No, object detection
Re: Scoped binding of a method to an object
This sort of decoration is nice and it's how I usually do this right now, but this requires me to wrap every array with an `XArray` call which is tedious, not to mention stuff like `.map` or `.reduce` would still return an Array which would result in more endless wrapping. On Sun, Oct 13, 2013 at 11:53 PM, Rick Waldron waldron.r...@gmail.comwrote: On Sun, Oct 13, 2013 at 2:00 PM, Benjamin (Inglor) Gruenbaum ing...@gmail.com wrote: Brendan Eich bren...@mozilla.com wrote: No, object detection, polyfilling, and even prollyfilling are common and successful adaptationsp on the Web. Polyfilling is great _after_ the method has already been added to the spec. I'm completely fine with adding an Array.prototype.map shim to IE8, the problem with adding a method that's not on the prototype yet is that it'll fail in case the spec is different from the implementation I chose. If you mentioned PrototypeJS, its `.bind` method is one such example. Your subject recalls a defunct proposal to add lexically-scoped but heap-based -- therefore object property-lookup performance hindering -- extension properties. I have to say this surprises me, a performance issue is the last thing I expected. What about attaching a prototype as a closure variable, something (and this is a syntax I __don't__ like) like: ``` (function(use Array){ Array.prototype.contains = function() { ... ... // any code here has access to .contains, code that did not originate here does not have such access, much like a closure. // other code is free to use Array without any collisions. })() ``` Another solution is creating your own subclass with custom methods... class XArray extends Array { constructor(...args) { super(...args); } contains(arg) { ... } } Then all code in this application uses XArray and gets its custom contains Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Scoped binding of a method to an object
Yeah, I don't see how it's going to happen either. Now that I get you meant dynamic as in contrary to lexical scoping having scoped object extensions seems very counter intuitive - especially given the direction the language is heading. Thanks for the discussion. On Mon, Oct 14, 2013 at 1:36 AM, Brendan Eich bren...@mozilla.com wrote: Benjamin (Inglor) Gruenbaum mailto:ing...@gmail.com October 13, 2013 2:28 PM Thanks, this really helped me understand the underlying issue here forcing dynamic resolution of scope here. It sounds a lot harder than I initially thought I have to say the fact this is so deeply rooted in the language semantics is somewhat surprising to me. That said, I think I see why behavioral typing would be act like this and I expect this to still be a lot harder than I imagine. Here is a counterexample based on the strawman's syntax: ... When I pass a parameter `a` to a function and call `a.where` , whether or not it's an extension method - don't I still have to do dynamic scope resolution? That's not dynamic scope, first (dynamic scope refers to scoping where an *unqualified* name's meaning cannot be determined lexically -- e.g., with or the global object in JS; inline event handlers in the DOM). Doesn't it still have to walk the prototype chain until I find `.where` - just like if I pass an array-like with `.splice` and send it to a method using it and it has to figure out it's not Array.prototype.splice? Of course. The meaning a dot-qualified name in JS indeed depends on prototype lookup. But the parameters to that lookup procedure are the starting (directly referenced) object and the property name -- and not the scope in addition, or any equivalent transformation (e.g., my ?: example -- not also it used instanceof and did not work when a direct shadowing method existed on the array). Off the top of my head - what about for the duration of the scope of these methods we have a prototype right after Array.prototype - in this scenario. Doesn't this make `c` go to Object.prototype.where and then String.prototype.select and all `b` does is another prototype chain look up before reaching the extension? This is probably another naive suggestion though. It is, if you mean dynamically altering the prototype chain of standard objects within a lexical extent. That does create dynamic scope, since the call graph is not statically decidable in general in JS, and calls out of the lexical extent would see the prototype chain extension too. Even if we could pin down the call graph, we do not want arbitrary mutations going in and out of scope of prototype chains. Anyway, I think at this point we've established what is required for any scoped object extensions. Please draw the conclusion. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: what kind of problem is this fat arrow feature trying to solve ?
There are two things here: - In JS I (as well as most code in libraries I read) tend to use function expressions a lot. The arrow notation is easier to read in my opinion. It's shorter and more concise. That's a weak argument for it, but I think just making the language more concise is an argument on its own. - While we're making function expressions shorter, let's fix `this` function expresisons. Pretty much every host environment be it node, the web browser or embedding uses deferred execution and event loop driven concurrency at some level. While there is nothing in JavaScript itself that dictates this sort of concurrency in practice events are used extensively when coding JavaScript. Using an object and adding handlers that need a reference to that object is very common in the browser and in node. It's very common in practice and having lexical this in arrow functions seems very useful. An indicator might be that in languages that support it like CoffeeScript you see it used all the time, and the fact you see people using the `this=that/self/_this` pattern all the time. That pattern introduces its own set of problems - for example it creates a closure scope where one might not be needed and it's boilerplate. Having fat arrow lets us solve that. Benjamin Gruenbaum -- Forwarded message -- From: Andrea Giammarchi andrea.giammar...@gmail.com To: Tab Atkins Jr. jackalm...@gmail.com Cc: es-discuss@mozilla.org es-discuss@mozilla.org Date: Tue, 1 Oct 2013 19:35:28 -0700 Subject: Re: what kind of problem is this fat arrow feature trying to solve ? setTimeout accept extra arguments ... I write JavaScript that uses this feature. `setTimeout(callback, delay, arg1, arg2, argN, evenAnObject);` so fat arrow does not solve much here, I can use self as first argument and I am good. `forEach` and all other arrays accept a second argument `array.forEach(doStuff, boundContextObject);` so fat arrow does not solve a thing in mostly all Array extras. for **DOM** I use handlers as specified by **W3C** so that `{handleEvent: function () {this}}` works better than any mess I could create with callbacks that I won't be unable to remove later on (as I've said) ... so I can use `removeEventListener(this)` in every method handled by that object. So I actually wonder what kind of JavaScript **you** write because this was a honest question but probably ... people not familiar with JS are the answer: since developers ignore part of JS specs available since every then we need a fat arrow to break old syntax to make the creation of self bound function easier. This would be already an answer so thanks for participating. br ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: modulu, Raul's Array map example
I just asked Raul's weird syntax question in SO and tried to answer it myself. Going through the spec, I have to admit that he has a point and things could be clearer. I think the JS spec being good is a big factor not only for implementers but for developers too and it could be better :) However, admittedly I'm not a great writer myself and I don't know how the spec itself could be clearer in this case, and it was good *enough *for me as someone who has already read the spec to walk through. It would be great if that would be the case for new developers too. http://stackoverflow.com/questions/18947892/creating-range-in-js-strange-syntax/ The exact same thing goes to modulo in the spec Benjamin -- Forwarded message -- From: Brendan Eich bren...@mozilla.com To: raul mihaila raul.miha...@gmail.com Cc: es-discuss@mozilla.org Date: Sat, 21 Sep 2013 13:21:24 -0700 Subject: Re: modulo Since no one else replied, I will take a stab. raul mihaila mailto:raul.miha...@gmail.com** September 17, 2013 2:46 PM If I understand correctly, q = floor(x / y), in x - k = q x y, where k = x modulo y. If this is correct I think that such a note would be nice to have for non-mathematicians. :) It follows from 5.2, Algorithm Conventions, specifically: The mathematical function floor(x) yields the largest integer (closest to positive infinity) that is not larger than x. NOTE floor(x) = x-(x modulo 1). /be Raul M __**_ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss -- Forwarded message -- From: Jason Orendorff jason.orendo...@gmail.com To: Brandon Benvie bben...@mozilla.com Cc: es-discuss es-discuss@mozilla.org Date: Sat, 21 Sep 2013 17:50:29 -0500 Subject: Re: [[Invoke]] and implicit method calls On Fri, Sep 20, 2013 at 6:27 PM, Brandon Benvie bben...@mozilla.com wrote: Actually, taking the precedent of removing getPropertyDescriptor, it's has that would be removed. I think the logic of the current design is: primitives we keep; high-level operations that correspond to everyday syntax built into the language from of old (get/set/has/enumerate), we keep. But .hasOwn, like .getPropertyDescriptor, is neither. -j -- Forwarded message -- From: raul mihaila raul.miha...@gmail.com To: Brendan Eich bren...@mozilla.com Cc: es-discuss@mozilla.org Date: Sun, 22 Sep 2013 13:29:58 +0300 Subject: Re: modulo I saw that. I'm sure the spec is clear enough for implementers. Somebody mentioned that book authors should explain the spec to the developers. But the books aren't enough. For example, I didn't see something like this in any JS book that I've read. Array.apply(null, { length: 5 }).map(Number.call, Number); https://twitter.com/cowboy/status/288702647479984128 When an empty array or an 'empty array-like object' (but with a valid length property that is greater than 0) is used in the apply method, you'd think that no arguments are actually passed, because it's not intuitive to think otherwise. Only when you read the spec you see that something like this is possible. (I'm not saying that there's absolutely no book that explains this, but I can't read them all). I don't know what can be done... Regarding the modulo/floor section, I would prefer something like this instead: The mathematical function floor(*x*) produces the largest integer (closest to positive infinity) that is not larger than x. The notation *x* modulo *y* (y must be finite and nonzero) computes a value k of the same sign as y (or zero) such that abs(*k*) abs(*y*) and *x*-*k* = *q* × y, where q = floor(x / y). NOTE floor(*x*) = *x*-(*x* modulo 1). Raul M On Sat, Sep 21, 2013 at 11:21 PM, Brendan Eich bren...@mozilla.comwrote: Since no one else replied, I will take a stab. raul mihaila mailto:raul.miha...@gmail.com** September 17, 2013 2:46 PM If I understand correctly, q = floor(x / y), in x - k = q x y, where k = x modulo y. If this is correct I think that such a note would be nice to have for non-mathematicians. :) It follows from 5.2, Algorithm Conventions, specifically: The mathematical function floor(x) yields the largest integer (closest to positive infinity) that is not larger than x. NOTE floor(x) = x-(x modulo 1). /be Raul M __**_ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: modulu, Raul's Array map example
Yeah sorry. English is not my first language. I definitely meant API. It's not as much about that specific case but about your point on the spec and developers. Thanks again. Benjamin On Sun, Sep 22, 2013 at 11:32 PM, Rick Waldron waldron.r...@gmail.comwrote: On Sunday, September 22, 2013, Benjamin (Inglor) Gruenbaum wrote: I just asked Raul's weird syntax question in SO and tried to answer it myself. Going through the spec, I have to admit that he has a point and things could be clearer. I think the JS spec being good is a big factor not only for implementers but for developers too and it could be better :) However, admittedly I'm not a great writer myself and I don't know how the spec itself could be clearer in this case, and it was good *enough *for me as someone who has already read the spec to walk through. It would be great if that would be the case for new developers too. http://stackoverflow.com/questions/18947892/creating-range-in-js-strange-syntax/ I think you mean API, not syntax. Using Array.apply(null, arraylike) where arraylike = some object with a length property to create an empty array isn't the sort of content that belongs in a normative specification—it's merely an interesting use of the language's API. The parts of the expression in Ben's tweet are all explicitly specified in the standard. Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss