Re: Promise capability support
my use-case is the exact opposite. in integration-level javascript, its impractical to have independent rejectors/error-handlers for dozens of integrated-components. its much easier to debug/refactor integration-code with a single, universal rejector/error-handler (all it does is log the error-stack and return a 404/500 to the server-request, or crash the app if client-side). on server-side, you can't do much except 404/500 if the db-request times-out, JSON.parse fails, etc. on client-side, crashing the app (and notifying user an error occured, and retry the request) is pretty much the only thing you can do when the server 404/500's. On 7/20/18, Bob Myers wrote: > I've used this pattern exactly twice in the large-scale app I'm working on > now. > One of those I was able to eliminate after I thought harder about the > problem. > The other I eventually replaced with the following kind of pattern: > > ``` > function createPromise(resolver, rejector) { > return new Promise((resolve, reject) { > resolver.then(resolve); > rejector.then(reject); > }); > } > ``` > > Obviously the way this works it that to create a promise "controllable" > from "the outside", > you create your own resolver and rejector promises to pass to > `createPromise`, > such that they trigger when you need them to. > To put it a different way, instead of getting back and passing around > deferred-like objects, > which seems to be a massive anti-pattern to me, > the client creates their own promise-controlling promises designed to > trigger at the right time. > > Bob > > On Fri, Jul 20, 2018 at 9:07 AM Jordan Harband wrote: > >> I don't think the Deferred pattern is a good primitive to have in the >> language, and it's a pretty trivial primitive to write yourself if you >> need >> it. >> >> On Thu, Jul 19, 2018 at 6:13 PM, Isiah Meadows >> wrote: >> >>> Sometimes, it's *very* convenient to have those `resolve`/`reject` >>> functions as separate functions. However, when logic gets complex >>> enough and you need to send them elsewhere, save a continuation, etc., >>> it'd be much more convenient to just have a capability object exposed >>> more directly rather than go through the overhead and boilerplate of >>> going through the constructor with all its callback stuff and >>> everything. >>> >>> It's surprisingly not as uncommon as you'd expect for me to do this: >>> >>> ```js >>> let resolve, reject >>> let promise = new Promise((res, rej) => { >>> resolve = res >>> reject = rej >>> }) >>> ``` >>> >>> But doing this repeatedly gets *old*, especially when you've had to >>> write it several dozen times already. And it comes up frequently when >>> you're writing lower-level async utilities that require saving promise >>> state and resolving it in a way that's decoupled from the promise >>> itself. >>> >>> - >>> >>> So here's what I propose: >>> >>> - `Promise.newCapability()` - This basically returns the result of >>> [this][1], just wrapped in a suitable object whose prototype is >>> %PromiseCapabilityPrototype% (internal, no direct constructor). It's >>> subclass-safe, so you can do it with subclasses as appropriate, too. >>> - `capability.resolve(value)` - This invokes the implicit resolver >>> created for it, spec'd as [[Resolve]]. >>> - `capability.reject(value)` - This invokes the implicit rejector >>> created for it, spec'd as [[Reject]]. >>> - `capability.promise` - This returns the newly created promise. >>> >>> Yes, this is effectively a deferred API, but revealing constructors >>> are a bit too rigid and wasteful for some use cases. >>> >>> [1]: https://tc39.github.io/ecma262/#sec-newpromisecapability >>> >>> - >>> >>> Isiah Meadows >>> m...@isiahmeadows.com >>> www.isiahmeadows.com >>> ___ >>> 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 >> > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promise capability support
I've used this pattern exactly twice in the large-scale app I'm working on now. One of those I was able to eliminate after I thought harder about the problem. The other I eventually replaced with the following kind of pattern: ``` function createPromise(resolver, rejector) { return new Promise((resolve, reject) { resolver.then(resolve); rejector.then(reject); }); } ``` Obviously the way this works it that to create a promise "controllable" from "the outside", you create your own resolver and rejector promises to pass to `createPromise`, such that they trigger when you need them to. To put it a different way, instead of getting back and passing around deferred-like objects, which seems to be a massive anti-pattern to me, the client creates their own promise-controlling promises designed to trigger at the right time. Bob On Fri, Jul 20, 2018 at 9:07 AM Jordan Harband wrote: > I don't think the Deferred pattern is a good primitive to have in the > language, and it's a pretty trivial primitive to write yourself if you need > it. > > On Thu, Jul 19, 2018 at 6:13 PM, Isiah Meadows > wrote: > >> Sometimes, it's *very* convenient to have those `resolve`/`reject` >> functions as separate functions. However, when logic gets complex >> enough and you need to send them elsewhere, save a continuation, etc., >> it'd be much more convenient to just have a capability object exposed >> more directly rather than go through the overhead and boilerplate of >> going through the constructor with all its callback stuff and >> everything. >> >> It's surprisingly not as uncommon as you'd expect for me to do this: >> >> ```js >> let resolve, reject >> let promise = new Promise((res, rej) => { >> resolve = res >> reject = rej >> }) >> ``` >> >> But doing this repeatedly gets *old*, especially when you've had to >> write it several dozen times already. And it comes up frequently when >> you're writing lower-level async utilities that require saving promise >> state and resolving it in a way that's decoupled from the promise >> itself. >> >> - >> >> So here's what I propose: >> >> - `Promise.newCapability()` - This basically returns the result of >> [this][1], just wrapped in a suitable object whose prototype is >> %PromiseCapabilityPrototype% (internal, no direct constructor). It's >> subclass-safe, so you can do it with subclasses as appropriate, too. >> - `capability.resolve(value)` - This invokes the implicit resolver >> created for it, spec'd as [[Resolve]]. >> - `capability.reject(value)` - This invokes the implicit rejector >> created for it, spec'd as [[Reject]]. >> - `capability.promise` - This returns the newly created promise. >> >> Yes, this is effectively a deferred API, but revealing constructors >> are a bit too rigid and wasteful for some use cases. >> >> [1]: https://tc39.github.io/ecma262/#sec-newpromisecapability >> >> - >> >> Isiah Meadows >> m...@isiahmeadows.com >> www.isiahmeadows.com >> ___ >> 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 > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promise capability support
I don't think the Deferred pattern is a good primitive to have in the language, and it's a pretty trivial primitive to write yourself if you need it. On Thu, Jul 19, 2018 at 6:13 PM, Isiah Meadows wrote: > Sometimes, it's *very* convenient to have those `resolve`/`reject` > functions as separate functions. However, when logic gets complex > enough and you need to send them elsewhere, save a continuation, etc., > it'd be much more convenient to just have a capability object exposed > more directly rather than go through the overhead and boilerplate of > going through the constructor with all its callback stuff and > everything. > > It's surprisingly not as uncommon as you'd expect for me to do this: > > ```js > let resolve, reject > let promise = new Promise((res, rej) => { > resolve = res > reject = rej > }) > ``` > > But doing this repeatedly gets *old*, especially when you've had to > write it several dozen times already. And it comes up frequently when > you're writing lower-level async utilities that require saving promise > state and resolving it in a way that's decoupled from the promise > itself. > > - > > So here's what I propose: > > - `Promise.newCapability()` - This basically returns the result of > [this][1], just wrapped in a suitable object whose prototype is > %PromiseCapabilityPrototype% (internal, no direct constructor). It's > subclass-safe, so you can do it with subclasses as appropriate, too. > - `capability.resolve(value)` - This invokes the implicit resolver > created for it, spec'd as [[Resolve]]. > - `capability.reject(value)` - This invokes the implicit rejector > created for it, spec'd as [[Reject]]. > - `capability.promise` - This returns the newly created promise. > > Yes, this is effectively a deferred API, but revealing constructors > are a bit too rigid and wasteful for some use cases. > > [1]: https://tc39.github.io/ecma262/#sec-newpromisecapability > > - > > Isiah Meadows > m...@isiahmeadows.com > www.isiahmeadows.com > ___ > 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
Promise capability support
Sometimes, it's *very* convenient to have those `resolve`/`reject` functions as separate functions. However, when logic gets complex enough and you need to send them elsewhere, save a continuation, etc., it'd be much more convenient to just have a capability object exposed more directly rather than go through the overhead and boilerplate of going through the constructor with all its callback stuff and everything. It's surprisingly not as uncommon as you'd expect for me to do this: ```js let resolve, reject let promise = new Promise((res, rej) => { resolve = res reject = rej }) ``` But doing this repeatedly gets *old*, especially when you've had to write it several dozen times already. And it comes up frequently when you're writing lower-level async utilities that require saving promise state and resolving it in a way that's decoupled from the promise itself. - So here's what I propose: - `Promise.newCapability()` - This basically returns the result of [this][1], just wrapped in a suitable object whose prototype is %PromiseCapabilityPrototype% (internal, no direct constructor). It's subclass-safe, so you can do it with subclasses as appropriate, too. - `capability.resolve(value)` - This invokes the implicit resolver created for it, spec'd as [[Resolve]]. - `capability.reject(value)` - This invokes the implicit rejector created for it, spec'd as [[Reject]]. - `capability.promise` - This returns the newly created promise. Yes, this is effectively a deferred API, but revealing constructors are a bit too rigid and wasteful for some use cases. [1]: https://tc39.github.io/ecma262/#sec-newpromisecapability - Isiah Meadows m...@isiahmeadows.com www.isiahmeadows.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Small Proposal "!in"
> Throwing another operator name out there: what about `obj has "foo"` instead? As someone who has just been casually following this issue, I'd much prefer `has` over `on`. I was going to stay quiet, but only because I didn't have a better alternative. jhpratt On Thu, Jul 19, 2018 at 8:56 PM, Isiah Meadows wrote: > > "on" is a good name. Agree on separate. > > Throwing another operator name out there: what about `obj has "foo"` > instead? > > Either way, it's a new context-sensitive keyword in a very awkward > position. > > > * Non-clobbering mass assignment. Like Object.assign but that doesn't > > overwrite existing properties in the assignee. > > Could this be a new built-in function instead? Maybe, `Object.defaults`? > > Of course, this is a pretty hard tangent from the original thread. > > > Many use cases for hasOwnProperty could be better supported by Map, Set, > and > > Object.create(null) including: > > ... > > * Configuration objects. > > * Function options bundles. > > Not sure these would work well as maps, since it's far easier to just > use dictionary objects as named arguments. Clojure and Ruby are the > two main languages I know that use hash maps exclusively for named > parameters with any frequency, and that's because map/hash lookup is > as easy as property lookup. > > - Java and C++ use builders. (Java separates the two, while C++ merges > them.) > - C and Rust use structs. > - JavaScript and Lua use simple untyped objects. > - Kotlin, Scala, Swift, C#, Python, and Objective C use native named > arguments that are resolved internally. > - Even Ruby added sugar to support its common idiomatic use of hashes > as named arguments. > > - > > Isiah Meadows > m...@isiahmeadows.com > www.isiahmeadows.com > > > On Thu, Jul 19, 2018 at 1:03 PM, Mike Samuel wrote: > > > > > > On Thu, Jul 19, 2018 at 11:56 AM Michael Theriot > > wrote: > > For me, `hasOwn` with the different operand order isn't a problem, but > others may take a different view. Trying to keep the same order takes > us > down a route like `inOwn` which I can't say I care for. > >>> > >>> > >>> Nor me. I would argue for `on` (`'a' on b`), but that is a huge typo > >>> footgun (especially for Colemak users) and maybe isn't clear enough > about > >>> its semantics. I would argue that operators aren't camel cased in JS > >>> though, so `hasown`/`inown`. > >> > >> > >> For what it's worth I was also thinking of an "on" operator when reading > >> this message, so this is intuitive to me. I also think that is a > separate > >> idea to propose though. > > > > > > "on" is a good name. Agree on separate. > > > > > > Of couse the usage of `in` is most of the time is not recommended, but > it has it place. > >>> > >>> > >>> What places does it have? > >>> I remain unconvinced that `in` has significant enough use cases to > >>> warrant high-level ergonomics > >>> were it being proposed today. > >>> > >>> It exists, and it'll probably never be removed from the language, but I > >>> don't think it should be taught > >>> as a good part of the language, and linters should probably flag it. > >> > >> > >> Maybe a radical thought, but does this not apply to hasOwnProperty? If > you > >> have strong type management why test for a property? The one case I can > >> think of is parsing JSON but I handle that with destructuring. Are there > >> significant use cases for it? Should linters flag it? > > > > > > Good questions. > > Linters should flag > >x.hasOwnProperty(y) > > since if you're unsure whether x has an own property y you're probably > > unsure whether x has an own property 'hasOwnProperty'. > > > > IIRC, destructuring traverses prototypes so see caveat about library code > > and monkeypatching below. > > const { toString: f } = {} > > typeof f // 'funciton' > > > > You're right that in the middle of an application an instance's type > should > > determine whether a property is present. > > There are use cases at the periphery. > > > > Use cases in bleeding edge JS include > > * As you noted, operations on parsed JSON. Even if you use revivers to > > parse JSON to Maps instead of Objects > > you either need own property checks or Object.setPrototypeOf(parsed, > null) > > when populating the Map. > > * Non-clobbering mass assignment. Like Object.assign but that doesn't > > overwrite existing properties in the assignee. > > * Reliable hole detection in arrays: (1 !on [0, , 2]) > > * Adapters that use naming conventions between JS objects and external > > systems, like between database field names and JS property names. > > * Distinguishing between user-code-defined properties on a host object > like > > an HTML element and readonly host properties. > > > > Many use cases for hasOwnProperty could be better supported by Map, Set, > and > > Object.create(null) including: > > * Objects used as lookup tables. > > * Lookup tables with special purpose fallback logic like message bundles > > that
Re: Small Proposal "!in"
> "on" is a good name. Agree on separate. Throwing another operator name out there: what about `obj has "foo"` instead? Either way, it's a new context-sensitive keyword in a very awkward position. > * Non-clobbering mass assignment. Like Object.assign but that doesn't > overwrite existing properties in the assignee. Could this be a new built-in function instead? Maybe, `Object.defaults`? Of course, this is a pretty hard tangent from the original thread. > Many use cases for hasOwnProperty could be better supported by Map, Set, and > Object.create(null) including: > ... > * Configuration objects. > * Function options bundles. Not sure these would work well as maps, since it's far easier to just use dictionary objects as named arguments. Clojure and Ruby are the two main languages I know that use hash maps exclusively for named parameters with any frequency, and that's because map/hash lookup is as easy as property lookup. - Java and C++ use builders. (Java separates the two, while C++ merges them.) - C and Rust use structs. - JavaScript and Lua use simple untyped objects. - Kotlin, Scala, Swift, C#, Python, and Objective C use native named arguments that are resolved internally. - Even Ruby added sugar to support its common idiomatic use of hashes as named arguments. - Isiah Meadows m...@isiahmeadows.com www.isiahmeadows.com On Thu, Jul 19, 2018 at 1:03 PM, Mike Samuel wrote: > > > On Thu, Jul 19, 2018 at 11:56 AM Michael Theriot > wrote: For me, `hasOwn` with the different operand order isn't a problem, but others may take a different view. Trying to keep the same order takes us down a route like `inOwn` which I can't say I care for. >>> >>> >>> Nor me. I would argue for `on` (`'a' on b`), but that is a huge typo >>> footgun (especially for Colemak users) and maybe isn't clear enough about >>> its semantics. I would argue that operators aren't camel cased in JS >>> though, so `hasown`/`inown`. >> >> >> For what it's worth I was also thinking of an "on" operator when reading >> this message, so this is intuitive to me. I also think that is a separate >> idea to propose though. > > > "on" is a good name. Agree on separate. > > Of couse the usage of `in` is most of the time is not recommended, but it has it place. >>> >>> >>> What places does it have? >>> I remain unconvinced that `in` has significant enough use cases to >>> warrant high-level ergonomics >>> were it being proposed today. >>> >>> It exists, and it'll probably never be removed from the language, but I >>> don't think it should be taught >>> as a good part of the language, and linters should probably flag it. >> >> >> Maybe a radical thought, but does this not apply to hasOwnProperty? If you >> have strong type management why test for a property? The one case I can >> think of is parsing JSON but I handle that with destructuring. Are there >> significant use cases for it? Should linters flag it? > > > Good questions. > Linters should flag >x.hasOwnProperty(y) > since if you're unsure whether x has an own property y you're probably > unsure whether x has an own property 'hasOwnProperty'. > > IIRC, destructuring traverses prototypes so see caveat about library code > and monkeypatching below. > const { toString: f } = {} > typeof f // 'funciton' > > You're right that in the middle of an application an instance's type should > determine whether a property is present. > There are use cases at the periphery. > > Use cases in bleeding edge JS include > * As you noted, operations on parsed JSON. Even if you use revivers to > parse JSON to Maps instead of Objects > you either need own property checks or Object.setPrototypeOf(parsed, null) > when populating the Map. > * Non-clobbering mass assignment. Like Object.assign but that doesn't > overwrite existing properties in the assignee. > * Reliable hole detection in arrays: (1 !on [0, , 2]) > * Adapters that use naming conventions between JS objects and external > systems, like between database field names and JS property names. > * Distinguishing between user-code-defined properties on a host object like > an HTML element and readonly host properties. > > Many use cases for hasOwnProperty could be better supported by Map, Set, and > Object.create(null) including: > * Objects used as lookup tables. > * Lookup tables with special purpose fallback logic like message bundles > that fall back from locale 'aa-BB' to 'aa'. > * Configuration objects. > * Function options bundles. > but idiomatic JS hasn't caught up and some library code has to run on old > interpreters, so a transpiling `on` would be nice. > The last two are mostly an issue in library code that needs to be resilient > when loaded alongside monkeypatched prototypes. > > Honorable mention: > * for(...in...) iteration broken > solved by for(...of...): > > > ___ > es-discuss mailing list > es-discuss@mozilla.org >
Re: Feature proposal
I'm not a fan of the "Iteratable" object - it doesn't align with the corresponding existing concept of "iterables", and the iterable protocol is just an interface - there's no named object that corresponds to that type. What we really need is that pipeline operator to finally get figured out: https://github.com/tc39/proposal-pipeline-operator That wil address the primary need for things like these, without running you into issues of namespace collision. - Isiah Meadows m...@isiahmeadows.com www.isiahmeadows.com On Thu, Jul 19, 2018 at 11:38 AM, Nicolas B. Pierron wrote: > On Thu, Jul 19, 2018 at 12:53 PM, Nicolas B. Pierron > wrote: >>> On Wed, Jul 18, 2018 at 2:06 PM Nicolas B. Pierron >>> wrote: Stupid question, but why are some of these methods implemented on String, Array, TypedArray, Map and Set, while all of them are Iteratable? >>> >> Among list of nice Iteratable property that one might add, and which >> might not be part of the standard are things like: >> chain, take, skip, takeWhile, skipWhile, repeat, zip, enumerate, >> range, stepBy, … > > Apparently this already exists as a JS library: > https://fitzgen.github.io/wu.js/ > > -- > Nicolas B. Pierron ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: const {resolve} = Promise; // fails
> one without precedent in the language that's how languages move forward, right? > It also means you can't `Promise.resolve.call(SubPromise)` you can make it more complex and yet have a fallback to the invoker, not a real issue, just more rules to write down. ```js const withLazyBoundObjects = new WeakMap; const withLazyBoundMethods = obj => { const descriptors = Object.getOwnPropertyDescriptors(obj); Object.keys(descriptors).forEach(key => { const desc = descriptors[key]; const {value} = desc; if (desc.configurable && typeof value === 'function') { delete desc.value; delete desc.writable; desc.get = function () {"use strict"; const self = this || obj; let methods = withLazyBoundObjects.get(self); if (!methods) withLazyBoundObjects.set(self, methods = Object.create(null)); return methods[key] || (methods[key] = function () { return value.apply(this || self, arguments); }); }; } }); return Object.defineProperties(obj, descriptors); }; withLazyBoundMethods(Promise); class SubPromise extends Promise {} console.log([ (0,Promise.resolve)() instanceof SubPromise, Promise.resolve() instanceof SubPromise, (0,SubPromise.resolve)() instanceof SubPromise, SubPromise.resolve() instanceof SubPromise, Promise.resolve.call(SubPromise) instanceof SubPromise ]); // [false, false, true, true, true] ``` On Fri, Jul 20, 2018 at 1:59 AM Jordan Harband wrote: > That's certainly a clever solution, but one without precedent in the > language. It also means you can't `Promise.resolve.call(SubPromise)`, > although perhaps you could avoid that by skipping `.bind` and creating a > normal function wrapper inside the getter - I'm curious how that might be > implemented as well as specified. > > On Thu, Jul 19, 2018 at 4:54 PM, Andrea Giammarchi < > andrea.giammar...@gmail.com> wrote: > >> My code doesn't suffer what Domenic says. >> >> Once again: >> >> ```js >> const withLazyBoundObjects = new WeakMap; >> const withLazyBoundMethods = obj => { >> const descriptors = Object.getOwnPropertyDescriptors(obj); >> Object.keys(descriptors).forEach(key => { >> const desc = descriptors[key]; >> const {value} = desc; >> if (desc.configurable && typeof value === 'function') { >> delete desc.value; >> delete desc.writable; >> desc.get = function (...args) { >> let methods = withLazyBoundObjects.get(this || obj); >> if (!methods) >> withLazyBoundObjects.set(this, methods = Object.create(null)); >> return methods[key] || (methods[key] = value.bind(this)); >> }; >> } >> }); >> return Object.defineProperties(obj, descriptors); >> }; >> >> // patch the Promise >> withLazyBoundMethods(Promise); >> >> // have a class that extends Promise >> class SubPromise extends Promise {} >> >> // test inheritance >> SubPromise.resolve() instanceof SubPromise; // true >> (0,SubPromise.resolve)() instanceof SubPromise; // true >> >> // even the Promise ? >> Promise.resolve() instanceof SubPromise; // false, it's Promise >> (0,Promise.resolve)() instanceof SubPromise; // false, it's Promise >> ``` >> >> So, why cannot we have above behavior in core? >> >> >> >> On Fri, Jul 20, 2018 at 1:36 AM Jordan Harband wrote: >> >>> > TL;DR why aren't public static methods that need context **all** >>> lazily defined as bound (once) on demand? That would make every single >>> public static method consistent, accordingly with the Class you extracted >>> them from, right? That's not clever, that's usually developers expectations >>> because historically all public static methods don't need the Class to work. >>> >>> I believe >>> https://github.com/tc39/ecma262/issues/544#issuecomment-236487230 >>> answers this - specifically, expressing that the claimed better design is >>> for *nothing* to be bound. >>> >>> On Thu, Jul 19, 2018 at 4:22 PM, Andrea Giammarchi < >>> andrea.giammar...@gmail.com> wrote: >>> Reading that looks like nobody answered my question, explained through some code that wouldn't have any issue with subclassing. So no, there's no answer to my latest question in there, unless I've missed it. On Thu, Jul 19, 2018 at 7:56 PM Jordan Harband wrote: > This question has been answered here: > https://github.com/tc39/ecma262/issues/544 > > On Thu, Jul 19, 2018 at 9:27 AM, Andrea Giammarchi < > andrea.giammar...@gmail.com> wrote: > >> > Per the KISS principle, let’s avoid to be clever. >> >> I think my next code example is less clever, but the only reason I've >> written hacks or code was not to be advocated or adopted, just to explain >> what could happen internally. >> >> TL;DR why aren't public static methods that need context **all** >> lazily defined as bound (once) on demand? That would make every single >> public static method consistent, accordingly
Re: const {resolve} = Promise; // fails
That's certainly a clever solution, but one without precedent in the language. It also means you can't `Promise.resolve.call(SubPromise)`, although perhaps you could avoid that by skipping `.bind` and creating a normal function wrapper inside the getter - I'm curious how that might be implemented as well as specified. On Thu, Jul 19, 2018 at 4:54 PM, Andrea Giammarchi < andrea.giammar...@gmail.com> wrote: > My code doesn't suffer what Domenic says. > > Once again: > > ```js > const withLazyBoundObjects = new WeakMap; > const withLazyBoundMethods = obj => { > const descriptors = Object.getOwnPropertyDescriptors(obj); > Object.keys(descriptors).forEach(key => { > const desc = descriptors[key]; > const {value} = desc; > if (desc.configurable && typeof value === 'function') { > delete desc.value; > delete desc.writable; > desc.get = function (...args) { > let methods = withLazyBoundObjects.get(this || obj); > if (!methods) > withLazyBoundObjects.set(this, methods = Object.create(null)); > return methods[key] || (methods[key] = value.bind(this)); > }; > } > }); > return Object.defineProperties(obj, descriptors); > }; > > // patch the Promise > withLazyBoundMethods(Promise); > > // have a class that extends Promise > class SubPromise extends Promise {} > > // test inheritance > SubPromise.resolve() instanceof SubPromise; // true > (0,SubPromise.resolve)() instanceof SubPromise; // true > > // even the Promise ? > Promise.resolve() instanceof SubPromise; // false, it's Promise > (0,Promise.resolve)() instanceof SubPromise; // false, it's Promise > ``` > > So, why cannot we have above behavior in core? > > > > On Fri, Jul 20, 2018 at 1:36 AM Jordan Harband wrote: > >> > TL;DR why aren't public static methods that need context **all** >> lazily defined as bound (once) on demand? That would make every single >> public static method consistent, accordingly with the Class you extracted >> them from, right? That's not clever, that's usually developers expectations >> because historically all public static methods don't need the Class to work. >> >> I believe https://github.com/tc39/ecma262/issues/544# >> issuecomment-236487230 answers this - specifically, expressing that the >> claimed better design is for *nothing* to be bound. >> >> On Thu, Jul 19, 2018 at 4:22 PM, Andrea Giammarchi < >> andrea.giammar...@gmail.com> wrote: >> >>> Reading that looks like nobody answered my question, explained through >>> some code that wouldn't have any issue with subclassing. >>> >>> So no, there's no answer to my latest question in there, unless I've >>> missed it. >>> >>> On Thu, Jul 19, 2018 at 7:56 PM Jordan Harband wrote: >>> This question has been answered here: https://github.com/tc39/ ecma262/issues/544 On Thu, Jul 19, 2018 at 9:27 AM, Andrea Giammarchi < andrea.giammar...@gmail.com> wrote: > > Per the KISS principle, let’s avoid to be clever. > > I think my next code example is less clever, but the only reason I've > written hacks or code was not to be advocated or adopted, just to explain > what could happen internally. > > TL;DR why aren't public static methods that need context **all** > lazily defined as bound (once) on demand? That would make every single > public static method consistent, accordingly with the Class you extracted > them from, right? That's not clever, that's usually developers > expectations > because historically all public static methods don't need the Class to > work. > > On Thu, Jul 19, 2018 at 5:23 PM Claude Pache > wrote: > >> >> >> > Le 19 juil. 2018 à 16:32, Andrea Giammarchi < >> andrea.giammar...@gmail.com> a écrit : >> > >> > I know it's about subclassing, which is why I've asked why, once >> there's no context, the default/base one is not considered, but since >> everyone came back with the subclassing issue, which is actually what >> I've >> said myself on twitter about the current state, how about changing all >> public static methods that need it, to be getters ? >> > >> > ```js >> > class Promise { >> > #resolve(...args) { >> > return this.nativeImplementation(...args); >> > } >> > get resolve() { >> > return #resolve.bind(this); >> > } >> > } >> > ``` >> > >> > we could argue `Promise.resolve === Promise.resolve` should be >> preserved, as behavior, so that we need a lazy defined getter ... **but** >> why not making public static restructuring from known constructors work >> regardless, under all circumstances ? >> > >> >> Nice hack... But it imposes all subclasses of `Promise` that override >> the `resolve` method to use a similar trick, because the following will >> break: >> >> ```js >> class MyPromise extends Promise { >> static
Re: const {resolve} = Promise; // fails
My code doesn't suffer what Domenic says. Once again: ```js const withLazyBoundObjects = new WeakMap; const withLazyBoundMethods = obj => { const descriptors = Object.getOwnPropertyDescriptors(obj); Object.keys(descriptors).forEach(key => { const desc = descriptors[key]; const {value} = desc; if (desc.configurable && typeof value === 'function') { delete desc.value; delete desc.writable; desc.get = function (...args) { let methods = withLazyBoundObjects.get(this || obj); if (!methods) withLazyBoundObjects.set(this, methods = Object.create(null)); return methods[key] || (methods[key] = value.bind(this)); }; } }); return Object.defineProperties(obj, descriptors); }; // patch the Promise withLazyBoundMethods(Promise); // have a class that extends Promise class SubPromise extends Promise {} // test inheritance SubPromise.resolve() instanceof SubPromise; // true (0,SubPromise.resolve)() instanceof SubPromise; // true // even the Promise ? Promise.resolve() instanceof SubPromise; // false, it's Promise (0,Promise.resolve)() instanceof SubPromise; // false, it's Promise ``` So, why cannot we have above behavior in core? On Fri, Jul 20, 2018 at 1:36 AM Jordan Harband wrote: > > TL;DR why aren't public static methods that need context **all** lazily > defined as bound (once) on demand? That would make every single public > static method consistent, accordingly with the Class you extracted them > from, right? That's not clever, that's usually developers expectations > because historically all public static methods don't need the Class to work. > > I believe > https://github.com/tc39/ecma262/issues/544#issuecomment-236487230 answers > this - specifically, expressing that the claimed better design is for > *nothing* to be bound. > > On Thu, Jul 19, 2018 at 4:22 PM, Andrea Giammarchi < > andrea.giammar...@gmail.com> wrote: > >> Reading that looks like nobody answered my question, explained through >> some code that wouldn't have any issue with subclassing. >> >> So no, there's no answer to my latest question in there, unless I've >> missed it. >> >> On Thu, Jul 19, 2018 at 7:56 PM Jordan Harband wrote: >> >>> This question has been answered here: >>> https://github.com/tc39/ecma262/issues/544 >>> >>> On Thu, Jul 19, 2018 at 9:27 AM, Andrea Giammarchi < >>> andrea.giammar...@gmail.com> wrote: >>> > Per the KISS principle, let’s avoid to be clever. I think my next code example is less clever, but the only reason I've written hacks or code was not to be advocated or adopted, just to explain what could happen internally. TL;DR why aren't public static methods that need context **all** lazily defined as bound (once) on demand? That would make every single public static method consistent, accordingly with the Class you extracted them from, right? That's not clever, that's usually developers expectations because historically all public static methods don't need the Class to work. On Thu, Jul 19, 2018 at 5:23 PM Claude Pache wrote: > > > > Le 19 juil. 2018 à 16:32, Andrea Giammarchi < > andrea.giammar...@gmail.com> a écrit : > > > > I know it's about subclassing, which is why I've asked why, once > there's no context, the default/base one is not considered, but since > everyone came back with the subclassing issue, which is actually what I've > said myself on twitter about the current state, how about changing all > public static methods that need it, to be getters ? > > > > ```js > > class Promise { > > #resolve(...args) { > > return this.nativeImplementation(...args); > > } > > get resolve() { > > return #resolve.bind(this); > > } > > } > > ``` > > > > we could argue `Promise.resolve === Promise.resolve` should be > preserved, as behavior, so that we need a lazy defined getter ... **but** > why not making public static restructuring from known constructors work > regardless, under all circumstances ? > > > > Nice hack... But it imposes all subclasses of `Promise` that override > the `resolve` method to use a similar trick, because the following will > break: > > ```js > class MyPromise extends Promise { > static resolve() { > // do fancy stuff > return super.resolve() > } > } > > const {resolve} = MyPromise > > resolve() // TypeError: undefined is not an object > ``` > > Per the KISS principle, let’s avoid to be clever. > > —Claude > > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss >>> > ___ es-discuss mailing list es-discuss@mozilla.org
Re: JSON support for BigInt in Chrome/V8
I'm not sure why anything needs remembering - with no other knowledge except "how the thing you're trying to create is used", I'd hope that it's apparent whether it's an object or a primitive. On Thu, Jul 19, 2018 at 2:43 PM, kai zhu wrote: > reposting due to previous mail-rejection (vpn issue with gmail in china) > > >You already can't use `new` with `Symbol`, and you don't ever want to use > `new` with a primitive's constructor anyways. > > this rule would be *okay* if we limit the number of primitive-types in > the language to a small-number (maybe add BigDecimal, but that's it), > so its easy to remember. i'm already concerned that we have one too > many needless primitives (Symbol should've been an object similar to > Promise, and even more so since its use-case is marginal). > > adding more primitives at this point, will only make this > pedantic-rule look more like a wart, and trip-up beginners (and their > prejudice on the language's inconsistencies). it also complicates > integration-work on web-projects, due to difficulty baton-passing new > primitives around via JSON, and having to continually refactor > type-checks that rely on typeof. > > > > On 7/17/18, Andrea Giammarchi wrote: > > fair enough, so everything that is not `object` or `null` should never > use > > `new`. Is this somehow an indirect rule based on current specs or > actually > > part of the specification? > > > > > > > > On Tue, Jul 17, 2018 at 11:12 AM J Decker wrote: > > > >> > >> > >> On Tue, Jul 17, 2018 at 1:48 AM Andrea Giammarchi < > >> andrea.giammar...@gmail.com> wrote: > >> > >>> We miss a fundamental feature in JS, the ability to understand if a > >>> native constructor can be used with `new` or not. > >>> > >>> BigInt("553"); > >>> 553n > >>> > >>> new BigInt("553"); > >>> VM51:1 Uncaught TypeError: BigInt is not a constructor > >>> > >>> > >> ``` > >> typeof(5n) > >> "bigint" > >> ``` > >> > >> Uint8Array([]) > >>> VM54:1 Uncaught TypeError: Constructor Uint8Array requires 'new' > >>> > >>> new Uint8Array([]) > >>> Uint8Array [] > >>> > >>> Without that knowledge, any attempt to even think about a solution that > >>> would scale not only with BigInt but with everything else, is kinda > >>> futile. > >>> > >>> Best Regards. > ___ > 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: const {resolve} = Promise; // fails
> TL;DR why aren't public static methods that need context **all** lazily defined as bound (once) on demand? That would make every single public static method consistent, accordingly with the Class you extracted them from, right? That's not clever, that's usually developers expectations because historically all public static methods don't need the Class to work. I believe https://github.com/tc39/ecma262/issues/544#issuecomment-236487230 answers this - specifically, expressing that the claimed better design is for *nothing* to be bound. On Thu, Jul 19, 2018 at 4:22 PM, Andrea Giammarchi < andrea.giammar...@gmail.com> wrote: > Reading that looks like nobody answered my question, explained through > some code that wouldn't have any issue with subclassing. > > So no, there's no answer to my latest question in there, unless I've > missed it. > > On Thu, Jul 19, 2018 at 7:56 PM Jordan Harband wrote: > >> This question has been answered here: https://github.com/tc39/ >> ecma262/issues/544 >> >> On Thu, Jul 19, 2018 at 9:27 AM, Andrea Giammarchi < >> andrea.giammar...@gmail.com> wrote: >> >>> > Per the KISS principle, let’s avoid to be clever. >>> >>> I think my next code example is less clever, but the only reason I've >>> written hacks or code was not to be advocated or adopted, just to explain >>> what could happen internally. >>> >>> TL;DR why aren't public static methods that need context **all** lazily >>> defined as bound (once) on demand? That would make every single public >>> static method consistent, accordingly with the Class you extracted them >>> from, right? That's not clever, that's usually developers expectations >>> because historically all public static methods don't need the Class to work. >>> >>> On Thu, Jul 19, 2018 at 5:23 PM Claude Pache >>> wrote: >>> > Le 19 juil. 2018 à 16:32, Andrea Giammarchi < andrea.giammar...@gmail.com> a écrit : > > I know it's about subclassing, which is why I've asked why, once there's no context, the default/base one is not considered, but since everyone came back with the subclassing issue, which is actually what I've said myself on twitter about the current state, how about changing all public static methods that need it, to be getters ? > > ```js > class Promise { > #resolve(...args) { > return this.nativeImplementation(...args); > } > get resolve() { > return #resolve.bind(this); > } > } > ``` > > we could argue `Promise.resolve === Promise.resolve` should be preserved, as behavior, so that we need a lazy defined getter ... **but** why not making public static restructuring from known constructors work regardless, under all circumstances ? > Nice hack... But it imposes all subclasses of `Promise` that override the `resolve` method to use a similar trick, because the following will break: ```js class MyPromise extends Promise { static resolve() { // do fancy stuff return super.resolve() } } const {resolve} = MyPromise resolve() // TypeError: undefined is not an object ``` Per the KISS principle, let’s avoid to be clever. —Claude >>> ___ >>> 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: const {resolve} = Promise; // fails
Reading that looks like nobody answered my question, explained through some code that wouldn't have any issue with subclassing. So no, there's no answer to my latest question in there, unless I've missed it. On Thu, Jul 19, 2018 at 7:56 PM Jordan Harband wrote: > This question has been answered here: > https://github.com/tc39/ecma262/issues/544 > > On Thu, Jul 19, 2018 at 9:27 AM, Andrea Giammarchi < > andrea.giammar...@gmail.com> wrote: > >> > Per the KISS principle, let’s avoid to be clever. >> >> I think my next code example is less clever, but the only reason I've >> written hacks or code was not to be advocated or adopted, just to explain >> what could happen internally. >> >> TL;DR why aren't public static methods that need context **all** lazily >> defined as bound (once) on demand? That would make every single public >> static method consistent, accordingly with the Class you extracted them >> from, right? That's not clever, that's usually developers expectations >> because historically all public static methods don't need the Class to work. >> >> On Thu, Jul 19, 2018 at 5:23 PM Claude Pache >> wrote: >> >>> >>> >>> > Le 19 juil. 2018 à 16:32, Andrea Giammarchi < >>> andrea.giammar...@gmail.com> a écrit : >>> > >>> > I know it's about subclassing, which is why I've asked why, once >>> there's no context, the default/base one is not considered, but since >>> everyone came back with the subclassing issue, which is actually what I've >>> said myself on twitter about the current state, how about changing all >>> public static methods that need it, to be getters ? >>> > >>> > ```js >>> > class Promise { >>> > #resolve(...args) { >>> > return this.nativeImplementation(...args); >>> > } >>> > get resolve() { >>> > return #resolve.bind(this); >>> > } >>> > } >>> > ``` >>> > >>> > we could argue `Promise.resolve === Promise.resolve` should be >>> preserved, as behavior, so that we need a lazy defined getter ... **but** >>> why not making public static restructuring from known constructors work >>> regardless, under all circumstances ? >>> > >>> >>> Nice hack... But it imposes all subclasses of `Promise` that override >>> the `resolve` method to use a similar trick, because the following will >>> break: >>> >>> ```js >>> class MyPromise extends Promise { >>> static resolve() { >>> // do fancy stuff >>> return super.resolve() >>> } >>> } >>> >>> const {resolve} = MyPromise >>> >>> resolve() // TypeError: undefined is not an object >>> ``` >>> >>> Per the KISS principle, let’s avoid to be clever. >>> >>> —Claude >>> >>> >> ___ >> 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: JSON support for BigInt in Chrome/V8
reposting due to previous mail-rejection (vpn issue with gmail in china) >You already can't use `new` with `Symbol`, and you don't ever want to use >`new` with a primitive's constructor anyways. this rule would be *okay* if we limit the number of primitive-types in the language to a small-number (maybe add BigDecimal, but that's it), so its easy to remember. i'm already concerned that we have one too many needless primitives (Symbol should've been an object similar to Promise, and even more so since its use-case is marginal). adding more primitives at this point, will only make this pedantic-rule look more like a wart, and trip-up beginners (and their prejudice on the language's inconsistencies). it also complicates integration-work on web-projects, due to difficulty baton-passing new primitives around via JSON, and having to continually refactor type-checks that rely on typeof. On 7/17/18, Andrea Giammarchi wrote: > fair enough, so everything that is not `object` or `null` should never use > `new`. Is this somehow an indirect rule based on current specs or actually > part of the specification? > > > > On Tue, Jul 17, 2018 at 11:12 AM J Decker wrote: > >> >> >> On Tue, Jul 17, 2018 at 1:48 AM Andrea Giammarchi < >> andrea.giammar...@gmail.com> wrote: >> >>> We miss a fundamental feature in JS, the ability to understand if a >>> native constructor can be used with `new` or not. >>> >>> BigInt("553"); >>> 553n >>> >>> new BigInt("553"); >>> VM51:1 Uncaught TypeError: BigInt is not a constructor >>> >>> >> ``` >> typeof(5n) >> "bigint" >> ``` >> >> Uint8Array([]) >>> VM54:1 Uncaught TypeError: Constructor Uint8Array requires 'new' >>> >>> new Uint8Array([]) >>> Uint8Array [] >>> >>> Without that knowledge, any attempt to even think about a solution that >>> would scale not only with BigInt but with everything else, is kinda >>> futile. >>> >>> Best Regards. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: const {resolve} = Promise; // fails
This question has been answered here: https://github.com/tc39/ecma262/issues/544 On Thu, Jul 19, 2018 at 9:27 AM, Andrea Giammarchi < andrea.giammar...@gmail.com> wrote: > > Per the KISS principle, let’s avoid to be clever. > > I think my next code example is less clever, but the only reason I've > written hacks or code was not to be advocated or adopted, just to explain > what could happen internally. > > TL;DR why aren't public static methods that need context **all** lazily > defined as bound (once) on demand? That would make every single public > static method consistent, accordingly with the Class you extracted them > from, right? That's not clever, that's usually developers expectations > because historically all public static methods don't need the Class to work. > > On Thu, Jul 19, 2018 at 5:23 PM Claude Pache > wrote: > >> >> >> > Le 19 juil. 2018 à 16:32, Andrea Giammarchi < >> andrea.giammar...@gmail.com> a écrit : >> > >> > I know it's about subclassing, which is why I've asked why, once >> there's no context, the default/base one is not considered, but since >> everyone came back with the subclassing issue, which is actually what I've >> said myself on twitter about the current state, how about changing all >> public static methods that need it, to be getters ? >> > >> > ```js >> > class Promise { >> > #resolve(...args) { >> > return this.nativeImplementation(...args); >> > } >> > get resolve() { >> > return #resolve.bind(this); >> > } >> > } >> > ``` >> > >> > we could argue `Promise.resolve === Promise.resolve` should be >> preserved, as behavior, so that we need a lazy defined getter ... **but** >> why not making public static restructuring from known constructors work >> regardless, under all circumstances ? >> > >> >> Nice hack... But it imposes all subclasses of `Promise` that override the >> `resolve` method to use a similar trick, because the following will break: >> >> ```js >> class MyPromise extends Promise { >> static resolve() { >> // do fancy stuff >> return super.resolve() >> } >> } >> >> const {resolve} = MyPromise >> >> resolve() // TypeError: undefined is not an object >> ``` >> >> Per the KISS principle, let’s avoid to be clever. >> >> —Claude >> >> > ___ > 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: Small Proposal "!in"
On Thu, Jul 19, 2018 at 11:56 AM Michael Theriot < michael.lee.ther...@gmail.com> wrote: > For me, `hasOwn` with the different operand order isn't a problem, but >>> others may take a different view. Trying to keep the same order takes us >>> down a route like `inOwn` which I can't say I care for. >>> >> >> Nor me. I would argue for `on` (`'a' on b`), but that is a huge typo >> footgun (especially for Colemak users) and maybe isn't clear enough about >> its semantics. I would argue that operators aren't camel cased in JS >> though, so `hasown`/`inown`. >> > > For what it's worth I was also thinking of an "on" operator when reading > this message, so this is intuitive to me. I also think that is a separate > idea to propose though. > "on" is a good name. Agree on separate. > Of couse the usage of `in` is most of the time is not recommended, but it >>> has it place. >>> >> >> What places does it have? >> I remain unconvinced that `in` has significant enough use cases to >> warrant high-level ergonomics >> were it being proposed today. >> >> It exists, and it'll probably never be removed from the language, but I >> don't think it should be taught >> as a good part of the language, and linters should probably flag it. >> > > Maybe a radical thought, but does this not apply to hasOwnProperty? If you > have strong type management why test for a property? The one case I can > think of is parsing JSON but I handle that with destructuring. Are there > significant use cases for it? Should linters flag it? > Good questions. Linters should flag x.hasOwnProperty(y) since if you're unsure whether x has an own property y you're probably unsure whether x has an own property 'hasOwnProperty'. IIRC, destructuring traverses prototypes so see caveat about library code and monkeypatching below. const { toString: f } = {} typeof f // 'funciton' You're right that in the middle of an application an instance's type should determine whether a property is present. There are use cases at the periphery. Use cases in bleeding edge JS include * As you noted, operations on parsed JSON. Even if you use revivers to parse JSON to Maps instead of Objects you either need own property checks or Object.setPrototypeOf(parsed, null) when populating the Map. * Non-clobbering mass assignment. Like Object.assign but that doesn't overwrite existing properties in the assignee. * Reliable hole detection in arrays: (1 !on [0, , 2]) * Adapters that use naming conventions between JS objects and external systems, like between database field names and JS property names. * Distinguishing between user-code-defined properties on a host object like an HTML element and readonly host properties. Many use cases for hasOwnProperty could be better supported by Map, Set, and Object.create(null) including: * Objects used as lookup tables. * Lookup tables with special purpose fallback logic like message bundles that fall back from locale 'aa-BB' to 'aa'. * Configuration objects. * Function options bundles. but idiomatic JS hasn't caught up and some library code has to run on old interpreters, so a transpiling `on` would be nice. The last two are mostly an issue in library code that needs to be resilient when loaded alongside monkeypatched prototypes. Honorable mention: * for(...in...) iteration broken solved by for(...of...): ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: const {resolve} = Promise; // fails
> Per the KISS principle, let’s avoid to be clever. I think my next code example is less clever, but the only reason I've written hacks or code was not to be advocated or adopted, just to explain what could happen internally. TL;DR why aren't public static methods that need context **all** lazily defined as bound (once) on demand? That would make every single public static method consistent, accordingly with the Class you extracted them from, right? That's not clever, that's usually developers expectations because historically all public static methods don't need the Class to work. On Thu, Jul 19, 2018 at 5:23 PM Claude Pache wrote: > > > > Le 19 juil. 2018 à 16:32, Andrea Giammarchi > a écrit : > > > > I know it's about subclassing, which is why I've asked why, once there's > no context, the default/base one is not considered, but since everyone came > back with the subclassing issue, which is actually what I've said myself on > twitter about the current state, how about changing all public static > methods that need it, to be getters ? > > > > ```js > > class Promise { > > #resolve(...args) { > > return this.nativeImplementation(...args); > > } > > get resolve() { > > return #resolve.bind(this); > > } > > } > > ``` > > > > we could argue `Promise.resolve === Promise.resolve` should be > preserved, as behavior, so that we need a lazy defined getter ... **but** > why not making public static restructuring from known constructors work > regardless, under all circumstances ? > > > > Nice hack... But it imposes all subclasses of `Promise` that override the > `resolve` method to use a similar trick, because the following will break: > > ```js > class MyPromise extends Promise { > static resolve() { > // do fancy stuff > return super.resolve() > } > } > > const {resolve} = MyPromise > > resolve() // TypeError: undefined is not an object > ``` > > Per the KISS principle, let’s avoid to be clever. > > —Claude > > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: const {resolve} = Promise; // fails
Yes Michael, the `::` operator is the best thing ever proposed and got killed / pseudo replaced by another, completely different, operator that won't solve problems `::` would: the `|>` pipe one. I'm a big fan of the `::` operator, and if it were there, I would quite possibly also like the "per context" restructuring. On Thu, Jul 19, 2018 at 5:12 PM Michael Luder-Rosefield < rosyatran...@gmail.com> wrote: > At this point I can't ignore how much overlap there is between this and > the this-binding operator proposal > https://github.com/tc39/proposal-bind-operator > > ``` > const resolve = ::Promise.resolve; // takes and binds > ``` > > As someone who often extracts functions with deconstruction, I'd love for > there to be an extension to this proposal to handle this case. > > ``` > const { resolve, reject } = ::Promise; // ? > ``` > > That would leave the question though of what to do with nesting: > > ``` > const { fn1, foo: { fn2 } } = ::bar; // fn1 is bound to bar. Is fn2 bound > to bar, or foo? > ``` > > On Thu, 19 Jul 2018 at 15:58 Andrea Giammarchi < > andrea.giammar...@gmail.com> wrote: > >> I guess one example would be more explicative: why cannot public static >> methods be defined in a similar manner? >> >> ```js >> const withLazyBoundObjects = new WeakMap; >> const withLazyBoundMethods = obj => { >> const descriptors = Object.getOwnPropertyDescriptors(obj); >> Object.keys(descriptors).forEach(key => { >> const desc = descriptors[key]; >> const {value} = desc; >> if (desc.configurable && typeof value === 'function') { >> delete desc.value; >> delete desc.writable; >> desc.get = function (...args) { >> let methods = withLazyBoundObjects.get(this || obj); >> if (!methods) >> withLazyBoundObjects.set(this, methods = Object.create(null)); >> return methods[key] || (methods[key] = value.bind(this)); >> }; >> } >> }); >> return Object.defineProperties(obj, descriptors); >> }; >> >> // example >> const {resolve, reject} = withLazyBoundMethods(Promise); >> resolve(123).then(console.log); >> ``` >> >> On Thu, Jul 19, 2018 at 4:33 PM Andrea Giammarchi < >> andrea.giammar...@gmail.com> wrote: >> >>> sorry, that'd be `public get resolve()` and also `public #resolve()` so >>> nobody should be confused about the fact I'm talking about public static >>> methods. >>> >>> On Thu, Jul 19, 2018 at 4:32 PM Andrea Giammarchi < >>> andrea.giammar...@gmail.com> wrote: >>> I know it's about subclassing, which is why I've asked why, once there's no context, the default/base one is not considered, but since everyone came back with the subclassing issue, which is actually what I've said myself on twitter about the current state, how about changing all public static methods that need it, to be getters ? ```js class Promise { #resolve(...args) { return this.nativeImplementation(...args); } get resolve() { return #resolve.bind(this); } } ``` we could argue `Promise.resolve === Promise.resolve` should be preserved, as behavior, so that we need a lazy defined getter ... **but** why not making public static restructuring from known constructors work regardless, under all circumstances ? On Thu, Jul 19, 2018 at 4:11 PM T.J. Crowder < tj.crow...@farsightsoftware.com> wrote: > On Thu, Jul 19, 2018 at 12:56 PM, Andrea Giammarchi > wrote: > > Why cannot Promise methods fallback to Promise constructor when the > > class/context is not available? > > That sounds reasonable on first glance, but I'd be concerned about > what happens when you do it after subclassing: > > ```js > class MyPromise extends Promise { > // ...and adds some important feature... > } > // ... > const {resolve, reject} = MyPromise; > const p = resolve(); > p.someImportantFeature(/*...*/); // TypeError: undefined is not a > function > ``` > > ...since `resolve` fell back to `Promise`. That feels like a footgun. > Either subclassers would have to handle that, which they will forget to > do, > or it has to be a bit more complicated than just a simple fallback to ` > Promise` (I don't immediately know what that "more complicated" > answer would be.) > > -- T.J. Crowder > > ___ >> 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: Small Proposal "!in"
> > For me, `hasOwn` with the different operand order isn't a problem, but >> others may take a different view. Trying to keep the same order takes us >> down a route like `inOwn` which I can't say I care for. >> > > Nor me. I would argue for `on` (`'a' on b`), but that is a huge typo > footgun (especially for Colemak users) and maybe isn't clear enough about > its semantics. I would argue that operators aren't camel cased in JS > though, so `hasown`/`inown`. > For what it's worth I was also thinking of an "on" operator when reading this message, so this is intuitive to me. I also think that is a separate idea to propose though. Of couse the usage of `in` is most of the time is not recommended, but it >> has it place. >> > > What places does it have? > I remain unconvinced that `in` has significant enough use cases to warrant > high-level ergonomics > were it being proposed today. > > It exists, and it'll probably never be removed from the language, but I > don't think it should be taught > as a good part of the language, and linters should probably flag it. > Maybe a radical thought, but does this not apply to hasOwnProperty? If you have strong type management why test for a property? The one case I can think of is parsing JSON but I handle that with destructuring. Are there significant use cases for it? Should linters flag it? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Feature proposal
On Thu, Jul 19, 2018 at 12:53 PM, Nicolas B. Pierron wrote: >> On Wed, Jul 18, 2018 at 2:06 PM Nicolas B. Pierron >> wrote: >>> Stupid question, but why are some of these methods implemented on >>> String, Array, TypedArray, Map and Set, while all of them are >>> Iteratable? >> > Among list of nice Iteratable property that one might add, and which > might not be part of the standard are things like: > chain, take, skip, takeWhile, skipWhile, repeat, zip, enumerate, > range, stepBy, … Apparently this already exists as a JS library: https://fitzgen.github.io/wu.js/ -- Nicolas B. Pierron ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: const {resolve} = Promise; // fails
> Le 19 juil. 2018 à 16:32, Andrea Giammarchi a > écrit : > > I know it's about subclassing, which is why I've asked why, once there's no > context, the default/base one is not considered, but since everyone came back > with the subclassing issue, which is actually what I've said myself on > twitter about the current state, how about changing all public static methods > that need it, to be getters ? > > ```js > class Promise { > #resolve(...args) { > return this.nativeImplementation(...args); > } > get resolve() { > return #resolve.bind(this); > } > } > ``` > > we could argue `Promise.resolve === Promise.resolve` should be preserved, as > behavior, so that we need a lazy defined getter ... **but** why not making > public static restructuring from known constructors work regardless, under > all circumstances ? > Nice hack... But it imposes all subclasses of `Promise` that override the `resolve` method to use a similar trick, because the following will break: ```js class MyPromise extends Promise { static resolve() { // do fancy stuff return super.resolve() } } const {resolve} = MyPromise resolve() // TypeError: undefined is not an object ``` Per the KISS principle, let’s avoid to be clever. —Claude ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: const {resolve} = Promise; // fails
At this point I can't ignore how much overlap there is between this and the this-binding operator proposal https://github.com/tc39/proposal-bind-operator ``` const resolve = ::Promise.resolve; // takes and binds ``` As someone who often extracts functions with deconstruction, I'd love for there to be an extension to this proposal to handle this case. ``` const { resolve, reject } = ::Promise; // ? ``` That would leave the question though of what to do with nesting: ``` const { fn1, foo: { fn2 } } = ::bar; // fn1 is bound to bar. Is fn2 bound to bar, or foo? ``` On Thu, 19 Jul 2018 at 15:58 Andrea Giammarchi wrote: > I guess one example would be more explicative: why cannot public static > methods be defined in a similar manner? > > ```js > const withLazyBoundObjects = new WeakMap; > const withLazyBoundMethods = obj => { > const descriptors = Object.getOwnPropertyDescriptors(obj); > Object.keys(descriptors).forEach(key => { > const desc = descriptors[key]; > const {value} = desc; > if (desc.configurable && typeof value === 'function') { > delete desc.value; > delete desc.writable; > desc.get = function (...args) { > let methods = withLazyBoundObjects.get(this || obj); > if (!methods) > withLazyBoundObjects.set(this, methods = Object.create(null)); > return methods[key] || (methods[key] = value.bind(this)); > }; > } > }); > return Object.defineProperties(obj, descriptors); > }; > > // example > const {resolve, reject} = withLazyBoundMethods(Promise); > resolve(123).then(console.log); > ``` > > On Thu, Jul 19, 2018 at 4:33 PM Andrea Giammarchi < > andrea.giammar...@gmail.com> wrote: > >> sorry, that'd be `public get resolve()` and also `public #resolve()` so >> nobody should be confused about the fact I'm talking about public static >> methods. >> >> On Thu, Jul 19, 2018 at 4:32 PM Andrea Giammarchi < >> andrea.giammar...@gmail.com> wrote: >> >>> I know it's about subclassing, which is why I've asked why, once there's >>> no context, the default/base one is not considered, but since everyone came >>> back with the subclassing issue, which is actually what I've said myself on >>> twitter about the current state, how about changing all public static >>> methods that need it, to be getters ? >>> >>> ```js >>> class Promise { >>> #resolve(...args) { >>> return this.nativeImplementation(...args); >>> } >>> get resolve() { >>> return #resolve.bind(this); >>> } >>> } >>> ``` >>> >>> we could argue `Promise.resolve === Promise.resolve` should be >>> preserved, as behavior, so that we need a lazy defined getter ... **but** >>> why not making public static restructuring from known constructors work >>> regardless, under all circumstances ? >>> >>> >>> On Thu, Jul 19, 2018 at 4:11 PM T.J. Crowder < >>> tj.crow...@farsightsoftware.com> wrote: >>> On Thu, Jul 19, 2018 at 12:56 PM, Andrea Giammarchi wrote: > Why cannot Promise methods fallback to Promise constructor when the > class/context is not available? That sounds reasonable on first glance, but I'd be concerned about what happens when you do it after subclassing: ```js class MyPromise extends Promise { // ...and adds some important feature... } // ... const {resolve, reject} = MyPromise; const p = resolve(); p.someImportantFeature(/*...*/); // TypeError: undefined is not a function ``` ...since `resolve` fell back to `Promise`. That feels like a footgun. Either subclassers would have to handle that, which they will forget to do, or it has to be a bit more complicated than just a simple fallback to ` Promise` (I don't immediately know what that "more complicated" answer would be.) -- T.J. Crowder ___ > 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: Feature proposal
On Thu, Jul 19, 2018 at 8:54 AM Nicolas B. Pierron < nicolas.b.pier...@mozilla.com> wrote: > On Wed, Jul 18, 2018 at 6:43 PM, Mike Samuel wrote: > > Reverse is problematic on String. The index of a codepoint can't be > > subtracted from String.length since length is not the count of > codepoints. > > Don't take me wrong, I was not suggesting to add a `reverse` property. > I was suggesting to add the Iteratable object in the prototype chain > such that someone can implement extra property on the Iteratable / > Iteratable.prototype object. > My mistake. I assumed a goal was to allow implementing a generic findLastIndex in terms of find and reverse iterators. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Small Proposal "!in"
On Thu, Jul 19, 2018 at 10:40 AM Augusto Moura wrote: > Of couse the usage of `in` is most of the time is not recommended, but it > has it place. > What places does it have? I remain unconvinced that `in` has significant enough use cases to warrant high-level ergonomics were it being proposed today. It exists, and it'll probably never be removed from the language, but I don't think it should be taught as a good part of the language, and linters should probably flag it. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: const {resolve} = Promise; // fails
I guess one example would be more explicative: why cannot public static methods be defined in a similar manner? ```js const withLazyBoundObjects = new WeakMap; const withLazyBoundMethods = obj => { const descriptors = Object.getOwnPropertyDescriptors(obj); Object.keys(descriptors).forEach(key => { const desc = descriptors[key]; const {value} = desc; if (desc.configurable && typeof value === 'function') { delete desc.value; delete desc.writable; desc.get = function (...args) { let methods = withLazyBoundObjects.get(this || obj); if (!methods) withLazyBoundObjects.set(this, methods = Object.create(null)); return methods[key] || (methods[key] = value.bind(this)); }; } }); return Object.defineProperties(obj, descriptors); }; // example const {resolve, reject} = withLazyBoundMethods(Promise); resolve(123).then(console.log); ``` On Thu, Jul 19, 2018 at 4:33 PM Andrea Giammarchi < andrea.giammar...@gmail.com> wrote: > sorry, that'd be `public get resolve()` and also `public #resolve()` so > nobody should be confused about the fact I'm talking about public static > methods. > > On Thu, Jul 19, 2018 at 4:32 PM Andrea Giammarchi < > andrea.giammar...@gmail.com> wrote: > >> I know it's about subclassing, which is why I've asked why, once there's >> no context, the default/base one is not considered, but since everyone came >> back with the subclassing issue, which is actually what I've said myself on >> twitter about the current state, how about changing all public static >> methods that need it, to be getters ? >> >> ```js >> class Promise { >> #resolve(...args) { >> return this.nativeImplementation(...args); >> } >> get resolve() { >> return #resolve.bind(this); >> } >> } >> ``` >> >> we could argue `Promise.resolve === Promise.resolve` should be preserved, >> as behavior, so that we need a lazy defined getter ... **but** why not >> making public static restructuring from known constructors work regardless, >> under all circumstances ? >> >> >> On Thu, Jul 19, 2018 at 4:11 PM T.J. Crowder < >> tj.crow...@farsightsoftware.com> wrote: >> >>> On Thu, Jul 19, 2018 at 12:56 PM, Andrea Giammarchi >>> wrote: >>> > Why cannot Promise methods fallback to Promise constructor when the >>> > class/context is not available? >>> >>> That sounds reasonable on first glance, but I'd be concerned about what >>> happens when you do it after subclassing: >>> >>> ```js >>> class MyPromise extends Promise { >>> // ...and adds some important feature... >>> } >>> // ... >>> const {resolve, reject} = MyPromise; >>> const p = resolve(); >>> p.someImportantFeature(/*...*/); // TypeError: undefined is not a >>> function >>> ``` >>> >>> ...since `resolve` fell back to `Promise`. That feels like a footgun. >>> Either subclassers would have to handle that, which they will forget to do, >>> or it has to be a bit more complicated than just a simple fallback to ` >>> Promise` (I don't immediately know what that "more complicated" answer >>> would be.) >>> >>> -- T.J. Crowder >>> >>> ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Small Proposal "!in"
In most of the use cases of checking if a property is in the prototype chain (checking a protocol for example) you *do* want to trigger getters and Proxy traps. When interfacing with a object a developer doesn't need to be concerned with the implementation behind, if a getter or proxy trap does a intensive computation or has side effects, it's all bad class/object design fault. A common example when you want to check a property "return" rather than it's existence it's virtual properties or class refactoring: ``` js // old implementation class Foo { constructor() { this.foo = 46; } } // post refactoring class Foo { // implements something different // Product of refactoring, undefined it's a placeholder here //it can be any value that makes sense in the refactoring get foo() { return undefined; } set foo(_) {} } ``` Of course there's some use cases to use property check without triggering side effects (mostly when working with property descriptors), but the majority of "property existence check" lays on interface assertion and a typeof check it's ~generally~ the right choice. About the `!in` operator, I don't see any problem in it. Of couse the usage of `in` is most of the time is not recommended, but it has it place. Also it puts precedence to future operators (like the `hasOwn` proposed here). Em qui, 19 de jul de 2018 às 10:26, Michael Theriot < michael.lee.ther...@gmail.com> escreveu: > > 'string' === typeof document.createElement('input').type > > // true > > It should be noted this is a "loose check"; it does not determine whether > or not the property exists when its value equals undefined. It also > triggers getters, whereas `in` reports whether or not the property exists > without triggering a getter. > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > -- Augusto Moura ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: const {resolve} = Promise; // fails
sorry, that'd be `public get resolve()` and also `public #resolve()` so nobody should be confused about the fact I'm talking about public static methods. On Thu, Jul 19, 2018 at 4:32 PM Andrea Giammarchi < andrea.giammar...@gmail.com> wrote: > I know it's about subclassing, which is why I've asked why, once there's > no context, the default/base one is not considered, but since everyone came > back with the subclassing issue, which is actually what I've said myself on > twitter about the current state, how about changing all public static > methods that need it, to be getters ? > > ```js > class Promise { > #resolve(...args) { > return this.nativeImplementation(...args); > } > get resolve() { > return #resolve.bind(this); > } > } > ``` > > we could argue `Promise.resolve === Promise.resolve` should be preserved, > as behavior, so that we need a lazy defined getter ... **but** why not > making public static restructuring from known constructors work regardless, > under all circumstances ? > > > On Thu, Jul 19, 2018 at 4:11 PM T.J. Crowder < > tj.crow...@farsightsoftware.com> wrote: > >> On Thu, Jul 19, 2018 at 12:56 PM, Andrea Giammarchi >> wrote: >> > Why cannot Promise methods fallback to Promise constructor when the >> > class/context is not available? >> >> That sounds reasonable on first glance, but I'd be concerned about what >> happens when you do it after subclassing: >> >> ```js >> class MyPromise extends Promise { >> // ...and adds some important feature... >> } >> // ... >> const {resolve, reject} = MyPromise; >> const p = resolve(); >> p.someImportantFeature(/*...*/); // TypeError: undefined is not a function >> ``` >> >> ...since `resolve` fell back to `Promise`. That feels like a footgun. >> Either subclassers would have to handle that, which they will forget to do, >> or it has to be a bit more complicated than just a simple fallback to ` >> Promise` (I don't immediately know what that "more complicated" answer >> would be.) >> >> -- T.J. Crowder >> >> ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: const {resolve} = Promise; // fails
I know it's about subclassing, which is why I've asked why, once there's no context, the default/base one is not considered, but since everyone came back with the subclassing issue, which is actually what I've said myself on twitter about the current state, how about changing all public static methods that need it, to be getters ? ```js class Promise { #resolve(...args) { return this.nativeImplementation(...args); } get resolve() { return #resolve.bind(this); } } ``` we could argue `Promise.resolve === Promise.resolve` should be preserved, as behavior, so that we need a lazy defined getter ... **but** why not making public static restructuring from known constructors work regardless, under all circumstances ? On Thu, Jul 19, 2018 at 4:11 PM T.J. Crowder < tj.crow...@farsightsoftware.com> wrote: > On Thu, Jul 19, 2018 at 12:56 PM, Andrea Giammarchi > wrote: > > Why cannot Promise methods fallback to Promise constructor when the > > class/context is not available? > > That sounds reasonable on first glance, but I'd be concerned about what > happens when you do it after subclassing: > > ```js > class MyPromise extends Promise { > // ...and adds some important feature... > } > // ... > const {resolve, reject} = MyPromise; > const p = resolve(); > p.someImportantFeature(/*...*/); // TypeError: undefined is not a function > ``` > > ...since `resolve` fell back to `Promise`. That feels like a footgun. > Either subclassers would have to handle that, which they will forget to do, > or it has to be a bit more complicated than just a simple fallback to ` > Promise` (I don't immediately know what that "more complicated" answer > would be.) > > -- T.J. Crowder > > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Small Proposal "!in"
On Thu, 19 Jul 2018 at 14:48 Mike Samuel wrote: > On Thu, Jul 19, 2018 at 9:26 AM Michael Theriot < > michael.lee.ther...@gmail.com> wrote: > >> > 'string' === typeof document.createElement('input').type >> > // true >> >> It should be noted this is a "loose check"; it does not determine whether >> or not the property exists when its value equals undefined. It also >> triggers getters, whereas `in` reports whether or not the property exists >> without triggering a getter. >> > > Good point. `in` does trigger "has" proxy handlers though, so neither is > side-effect free. > Except I'd argue this is a desirable side effect in the case of `in` and less so in the case of a getter. Getters are more likely to be an intensive operation (for example, innerHTML) than a proxy `has` operation generally overriding the expected behaviour of the target object. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: const {resolve} = Promise; // fails
On Thu, Jul 19, 2018 at 12:56 PM, Andrea Giammarchi wrote: > Why cannot Promise methods fallback to Promise constructor when the > class/context is not available? That sounds reasonable on first glance, but I'd be concerned about what happens when you do it after subclassing: ```js class MyPromise extends Promise { // ...and adds some important feature... } // ... const {resolve, reject} = MyPromise; const p = resolve(); p.someImportantFeature(/*...*/); // TypeError: undefined is not a function ``` ...since `resolve` fell back to `Promise`. That feels like a footgun. Either subclassers would have to handle that, which they will forget to do, or it has to be a bit more complicated than just a simple fallback to ` Promise` (I don't immediately know what that "more complicated" answer would be.) -- T.J. Crowder ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Small Proposal "!in"
On Thu, 19 Jul 2018 at 14:44 T.J. Crowder wrote: > On Thu, Jul 19, 2018 at 12:32 PM, Andy Earnshaw > wrote: > > Although I support the idea of `!in` (for the same reasons as T.J. > Crowder > > mentioned, plus it's useful for duck typing), what some browsers do > isn't a > > great argument as modern browsers follow the spec more closely with > regards > > to inherited accessors like this and you'd never be able to use `!in` > for an > > older browser. > > Well, there's transpiling. > Good point. > > `!in` and `!instanceof` would be great additions to the operator sets. > > AND, agreeing with Mike Samuel, an ergonomic operator for `hasOwnProperty` > (that doesn't have the issues of being overridden, not being inherited > because `Object.prototype` isn't in the object's prototype chain, etc.) > would be a great addition. I don't see any reason they couldn't all be > part of the same proposal as they touch the same parts of the spec and > implementations. And agree that the own property ones would be the more > useful ones, but there are use cases for both. > > The immediate temptation is `hasOwn` and `!hasOwn`. My only concern is > that their operands would be in the opposite order to `in` and `!in`: > I'm not against this at all. I just think the arguments against `!in` aren't really arguments against it. Adding `!hasOwn` would give even more weight to an `!in` proposal, I think. > For me, `hasOwn` with the different operand order isn't a problem, but > others may take a different view. Trying to keep the same order takes us > down a route like `inOwn` which I can't say I care for. > Nor me. I would argue for `on` (`'a' on b`), but that is a huge typo footgun (especially for Colemak users) and maybe isn't clear enough about its semantics. I would argue that operators aren't camel cased in JS though, so `hasown`/`inown`. > > But I wonder if all of this discussion is useful. If someone *did* take > the time to work out the naming and do a proper draft proposal, perhaps a > Babel plugin, is there really any likelihood of someone championing it? I'd > see these contents: > > * `name !in obj`, `name notin obj`, or whatever it gets called > * `obj hasOwn name`, `name inOwn obj`, or whatever it gets called > * `obj !hasOwn name`, `name !inOwn obj`, or whatever it gets called > * `Reflect.hasOwn`, the "own" version of `Reflect.has` > * `Proxy` trap for `hasOwn` (even if the operator has a different name) > > Is there anyone appropriately-placed who can say "Yeah, if someone spends > the time to investigate this and put together a really proper proposal, I'm > willing to look at that proposal with an eye toward _possibly_ championing > it." I mean, if there's a 10% chance or better, it may be worth someone's > time. If there isn't, then... > `!in` and `!instanceof` are low hanging fruit (run the same steps as their counterparts but flip the result), better off in their own proposal. I don't know if you'd find a champion to do it, but I do think a lot of people would find them convenient. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Small Proposal "!in"
I still prefer truthy checks when logically valid. Otherwise a truthy check + [any other validity check in the logic]. I find `in` far too quirky and I'd rather never ever use it. I think `instanceof` is also a messy pattern. I've always preferred having an overridden method on the object that performs the necessary logic for that type, instead of if(x instanceof Y)... I find overridden method based code shorter at the point of use, and scales to many instances / permutations for type based logic. Therefore, I'd rather TC39 let these concepts like `in` and `instanceof` die quietly, and always focus on the more/most powerful ways of getting things done first. On Thu, 19 Jul 2018 at 19:14 T.J. Crowder wrote: > On Thu, Jul 19, 2018 at 12:32 PM, Andy Earnshaw > wrote: > > Although I support the idea of `!in` (for the same reasons as T.J. > Crowder > > mentioned, plus it's useful for duck typing), what some browsers do > isn't a > > great argument as modern browsers follow the spec more closely with > regards > > to inherited accessors like this and you'd never be able to use `!in` > for an > > older browser. > > Well, there's transpiling. > > > > `!in` and `!instanceof` would be great additions to the operator sets. > > AND, agreeing with Mike Samuel, an ergonomic operator for `hasOwnProperty` > (that doesn't have the issues of being overridden, not being inherited > because `Object.prototype` isn't in the object's prototype chain, etc.) > would be a great addition. I don't see any reason they couldn't all be > part of the same proposal as they touch the same parts of the spec and > implementations. And agree that the own property ones would be the more > useful ones, but there are use cases for both. > > The immediate temptation is `hasOwn` and `!hasOwn`. My only concern is > that their operands would be in the opposite order to `in` and `!in`: > > ```js > const o = Object.create({a: 1}); > o.b = 2; > console.log("a" in o); // true > console.log(o hasOwn "a"); // false > console.log("b" in o); // true > console.log(o hasOwn "b"); // true > ``` > > For me, `hasOwn` with the different operand order isn't a problem, but > others may take a different view. Trying to keep the same order takes us > down a route like `inOwn` which I can't say I care for. > > But I wonder if all of this discussion is useful. If someone *did* take > the time to work out the naming and do a proper draft proposal, perhaps a > Babel plugin, is there really any likelihood of someone championing it? I'd > see these contents: > > * `name !in obj`, `name notin obj`, or whatever it gets called > * `obj hasOwn name`, `name inOwn obj`, or whatever it gets called > * `obj !hasOwn name`, `name !inOwn obj`, or whatever it gets called > * `Reflect.hasOwn`, the "own" version of `Reflect.has` > * `Proxy` trap for `hasOwn` (even if the operator has a different name) > > Is there anyone appropriately-placed who can say "Yeah, if someone spends > the time to investigate this and put together a really proper proposal, I'm > willing to look at that proposal with an eye toward _possibly_ championing > it." I mean, if there's a 10% chance or better, it may be worth someone's > time. If there isn't, then... > > -- T.J. Crowder > ___ > 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: Small Proposal "!in"
It was a contrived example I threw together to make a point in 30 seconds. It may surprise you to know that it is not real world code. You talk about an "attacker" as if any code working in such a way is sensitive, but that is often not the case and leaving your functions intentionally generic allows third parties more room when working with it. > 'string' === typeof document.createElement('input').type > // true Again, you're missing the point, which is how that is one example of an object that doesn't 'own' all of its properties. As already mentioned, it also triggers a getter. Let's not also forget that not all code has to adhere to best practices. I use the `in` operator far more in the REPL/console or when I'm prototyping than I do when I'm performing robust checks in code. On Thu, 19 Jul 2018 at 13:23 Mike Samuel wrote: > On Thu, Jul 19, 2018 at 7:32 AM Andy Earnshaw > wrote: > >> Although I support the idea of `!in` (for the same reasons as T.J. >> Crowder mentioned, plus it's useful for duck typing), what some browsers do >> isn't a great argument as modern browsers follow the spec more closely with >> regards to inherited accessors like this and you'd never be able to use >> `!in` for an older browser. However, you do have a point in that accessors >> can live anywhere in the prototype chain and an object's properties may not >> necessarily be 'owned' by the object in question: >> >> document.createElement('input').hasOwnProperty('type') >> // false >> > > 'string' === typeof document.createElement('input').type > // true > > >> So far, the main argument against has been that `hasOwnProperty()` is >> recommended over `in` as a more robust check. I don't see how this is a >> valid concern, they clearly have different use cases and you're not going >> to solve that problem be excluding a negated `in` from the spec (`!(a in >> b)` is still easier to type than `!b.hasOwnProperty(a)`). There are plenty >> of valid use cases for `in`, not least duck typing as mentioned before: >> > > Agree re "not solving that problem by" > When I'm duck typing, I typically am testing typeof or truthiness of a > property, not just presence. > > function feed(duck) { >> if ('quackPitch' in duck && duck.canSwim) { >> duck.give(defrostedPeas); >> } >> } >> > > This code is brittle. An attacker may be able to deny service by getting > `{ "quackPitch": true, "canSwim": true }` to a JSON decoder, but would not > be able to trigger an exception if you tested with typeof instead of in. > > function robustFeed(duck) { > if (duck.canSwim && typeof duck.give === 'function') { > duck.give(defrostedPeas); > } > } > > `in` provides a weak, confusable kind of duck typing. > JSON decoding attacks allow forging objects that satisfy `in` predicates, > encouraging conflating > objects from an untrusted source with objects from trusted code. > These forgeries often would not pass stronger predicates that test for the > typeof required properties. > > >> `!in` and `!instanceof` would be great additions to the operator sets. >> > > Agree re !instanceof. I'm still not seeing where developers do and should > use `in` or `!in` on a regular basis. > > >> On Thu, 19 Jul 2018 at 12:06 Tobias Buschor >> wrote: >> >>> There are valid use-cases. >>> As an example, some browsers have "onfocus" as an own property of >>> "window", some as an inherited. >>> >>> ```js >>> if ('onfocus' !in window) { >>> // polyfill onfocus... >>> } >>> ``` >>> >>> >>> Am Mi., 18. Juli 2018 um 18:32 Uhr schrieb Mike Samuel < >>> mikesam...@gmail.com>: >>> On Wed, Jul 18, 2018 at 12:21 PM Michael Theriot < michael.lee.ther...@gmail.com> wrote: > I think it is irrelevant; the operator already exists and I would > assume if you want the negation of it you are using it correctly in the > first place. Otherwise are you not just arguing for its removal > altogether? > But to answer your question one case that comes to mind is trapping > get/has > in a proxy handler. Why should we assume that only people who consistently use `in` correctly would want the negation? It seems that people who use it incorrectly because they are confused about the precise semantics or don't care might want the negation too. If there are more of the latter then we should not assume what you assume. Proxy handler code is important, but very few developers will ever write a proxy handler over their careers, so this seems like a marginal use case. Besides, Reflect.has is probably a better choice in a proxy handler. I am not arguing for removing `in`. That would break the web. I am just arguing for prioritizing changes that provide features that more closely match the semantics developers typically want over making it more convenient to write code that seems to work in casual testing but has
Re: Small Proposal "!in"
On Thu, Jul 19, 2018 at 2:44 PM, T.J. Crowder < tj.crow...@farsightsoftware.com> wrote: > Is there anyone appropriately-placed who can say "Yeah, if someone spends > the time to investigate this and put together a really proper proposal, I'm > willing to look at that proposal with an eye toward _possibly_ championing > it." Apologies, Mike, I just realized you're a potential champion. Just in case you read that as seeming a bit off... :-) -- T.J. Crowder ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Small Proposal "!in"
On Thu, Jul 19, 2018 at 9:26 AM Michael Theriot < michael.lee.ther...@gmail.com> wrote: > > 'string' === typeof document.createElement('input').type > > // true > > It should be noted this is a "loose check"; it does not determine whether > or not the property exists when its value equals undefined. It also > triggers getters, whereas `in` reports whether or not the property exists > without triggering a getter. > Good point. `in` does trigger "has" proxy handlers though, so neither is side-effect free. > ___ > 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: Small Proposal "!in"
On Thu, Jul 19, 2018 at 12:32 PM, Andy Earnshaw wrote: > Although I support the idea of `!in` (for the same reasons as T.J. Crowder > mentioned, plus it's useful for duck typing), what some browsers do isn't a > great argument as modern browsers follow the spec more closely with regards > to inherited accessors like this and you'd never be able to use `!in` for an > older browser. Well, there's transpiling. > `!in` and `!instanceof` would be great additions to the operator sets. AND, agreeing with Mike Samuel, an ergonomic operator for `hasOwnProperty` (that doesn't have the issues of being overridden, not being inherited because ` Object.prototype` isn't in the object's prototype chain, etc.) would be a great addition. I don't see any reason they couldn't all be part of the same proposal as they touch the same parts of the spec and implementations. And agree that the own property ones would be the more useful ones, but there are use cases for both. The immediate temptation is `hasOwn` and `!hasOwn`. My only concern is that their operands would be in the opposite order to `in` and `!in`: ```js const o = Object.create({a: 1}); o.b = 2; console.log("a" in o); // true console.log(o hasOwn "a"); // false console.log("b" in o); // true console.log(o hasOwn "b"); // true ``` For me, `hasOwn` with the different operand order isn't a problem, but others may take a different view. Trying to keep the same order takes us down a route like `inOwn` which I can't say I care for. But I wonder if all of this discussion is useful. If someone *did* take the time to work out the naming and do a proper draft proposal, perhaps a Babel plugin, is there really any likelihood of someone championing it? I'd see these contents: * `name !in obj`, `name notin obj`, or whatever it gets called * `obj hasOwn name`, `name inOwn obj`, or whatever it gets called * `obj !hasOwn name`, `name !inOwn obj`, or whatever it gets called * `Reflect.hasOwn`, the "own" version of `Reflect.has` * `Proxy` trap for `hasOwn` (even if the operator has a different name) Is there anyone appropriately-placed who can say "Yeah, if someone spends the time to investigate this and put together a really proper proposal, I'm willing to look at that proposal with an eye toward _possibly_ championing it." I mean, if there's a 10% chance or better, it may be worth someone's time. If there isn't, then... -- T.J. Crowder ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: const {resolve} = Promise; // fails
> Le 19 juil. 2018 à 13:56, Andrea Giammarchi a > écrit : > > > Compared to every other public static method in ECMAScript that works, > including those methods that might need the contextual class, as it is for > the Array.from case. > > ```js > const {from} = Array; > > from({0: 'abc', length: 1}); // ["abc"] // all good > ``` That pattern falls apart when subclassing: ```js class ImprovedArray extends Array { /* implementation NOT overriding the `from` static method */ } const {from} = ImprovedArray from({0: 'abc', length: 1}) // Array instance instead of ImprovedArray instance ``` So, no, the `Array.from` precedent is a bad one. —Claude ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Small Proposal "!in"
> 'string' === typeof document.createElement('input').type > // true It should be noted this is a "loose check"; it does not determine whether or not the property exists when its value equals undefined. It also triggers getters, whereas `in` reports whether or not the property exists without triggering a getter. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Feature proposal
On Wed, Jul 18, 2018 at 6:43 PM, Mike Samuel wrote: > On Wed, Jul 18, 2018 at 2:06 PM Nicolas B. Pierron > wrote: >> Stupid question, but why are some of these methods implemented on >> String, Array, TypedArray, Map and Set, while all of them are >> Iteratable? > > > String is different from the others. > The String index methods deal with a contiguous subsequence of the sequence, > not the index of an element in the sequence. I am not sure why this would prevent us from adding an Iteratable object with common properties. `Iteratable.prototype.foo` can exist at the same time as `String.prototype.foo`, and calling the `foo` property on a String will result in calling `String.prototype.foo`. Also one could implement a naïve/default implementation of `reverseOrder` which allocates a temporary array for object which have no random accesses capabilities. Iteratable.prototype.reverseOrder = function* () { for (let e of [...this].reverse()) yield e; } ``` >> >> If we were to add all these methods on Iteratable, then one could add >> a `reverse` generator property on Iteratable. > > > Reverse is problematic on String. The index of a codepoint can't be > subtracted from String.length since length is not the count of codepoints. Don't take me wrong, I was not suggesting to add a `reverse` property. I was suggesting to add the Iteratable object in the prototype chain such that someone can implement extra property on the Iteratable / Iteratable.prototype object. Among list of nice Iteratable property that one might add, and which might not be part of the standard are things like: chain, take, skip, takeWhile, skipWhile, repeat, zip, enumerate, range, stepBy, … Another option would be to just add a property named `iter` which returns an Iteratable object. -- Nicolas B. Pierron ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Small Proposal "!in"
On Thu, Jul 19, 2018 at 7:32 AM Andy Earnshaw wrote: > Although I support the idea of `!in` (for the same reasons as T.J. Crowder > mentioned, plus it's useful for duck typing), what some browsers do isn't a > great argument as modern browsers follow the spec more closely with regards > to inherited accessors like this and you'd never be able to use `!in` for > an older browser. However, you do have a point in that accessors can live > anywhere in the prototype chain and an object's properties may not > necessarily be 'owned' by the object in question: > > document.createElement('input').hasOwnProperty('type') > // false > 'string' === typeof document.createElement('input').type // true > So far, the main argument against has been that `hasOwnProperty()` is > recommended over `in` as a more robust check. I don't see how this is a > valid concern, they clearly have different use cases and you're not going > to solve that problem be excluding a negated `in` from the spec (`!(a in > b)` is still easier to type than `!b.hasOwnProperty(a)`). There are plenty > of valid use cases for `in`, not least duck typing as mentioned before: > Agree re "not solving that problem by" When I'm duck typing, I typically am testing typeof or truthiness of a property, not just presence. function feed(duck) { > if ('quackPitch' in duck && duck.canSwim) { > duck.give(defrostedPeas); > } > } > This code is brittle. An attacker may be able to deny service by getting `{ "quackPitch": true, "canSwim": true }` to a JSON decoder, but would not be able to trigger an exception if you tested with typeof instead of in. function robustFeed(duck) { if (duck.canSwim && typeof duck.give === 'function') { duck.give(defrostedPeas); } } `in` provides a weak, confusable kind of duck typing. JSON decoding attacks allow forging objects that satisfy `in` predicates, encouraging conflating objects from an untrusted source with objects from trusted code. These forgeries often would not pass stronger predicates that test for the typeof required properties. > `!in` and `!instanceof` would be great additions to the operator sets. > Agree re !instanceof. I'm still not seeing where developers do and should use `in` or `!in` on a regular basis. > On Thu, 19 Jul 2018 at 12:06 Tobias Buschor > wrote: > >> There are valid use-cases. >> As an example, some browsers have "onfocus" as an own property of >> "window", some as an inherited. >> >> ```js >> if ('onfocus' !in window) { >> // polyfill onfocus... >> } >> ``` >> >> >> Am Mi., 18. Juli 2018 um 18:32 Uhr schrieb Mike Samuel < >> mikesam...@gmail.com>: >> >>> >>> >>> On Wed, Jul 18, 2018 at 12:21 PM Michael Theriot < >>> michael.lee.ther...@gmail.com> wrote: >>> I think it is irrelevant; the operator already exists and I would assume if you want the negation of it you are using it correctly in the first place. Otherwise are you not just arguing for its removal altogether? But to answer your question one case that comes to mind is trapping get/has in a proxy handler. >>> >>> >>> Why should we assume that only people who consistently use `in` >>> correctly would want the negation? It seems that people who use it >>> incorrectly because they are confused about the precise semantics or don't >>> care might want the negation too. If there are more of the latter then we >>> should not assume what you assume. >>> >>> Proxy handler code is important, but very few developers will ever write >>> a proxy handler over their careers, so this seems like a marginal use case. >>> Besides, Reflect.has is probably a better choice in a proxy handler. >>> >>> I am not arguing for removing `in`. That would break the web. I am >>> just arguing for prioritizing changes that provide features that more >>> closely match the semantics developers typically want over making it more >>> convenient to write code that seems to work in casual testing but has >>> subtly wrong semantics. >>> >>> >>> >>> >>> >>> >>> On Wednesday, July 18, 2018, Mike Samuel wrote: > > > On Wed, Jul 18, 2018 at 11:05 AM Michael Theriot < > michael.lee.ther...@gmail.com> wrote: > >> I think `in` and `instanceof` could both benefit from having negated >> versions. >> >> Assuming the developer is using `in` correctly, hasOwnProperty >> concerns are irrelevant. Either way they would attempt to use !(a in b), >> not !hasOwnProperty. >> > > Why should we assume the developer is using `in` correctly? > Apologies if I buried my question at the end. It was, what are the > use cases for `in` that would not be better served by an ergonomic, infix > hasOwnProperty? > > > Same reason we don't use... >> !(a == b) // a != b >> !(a === b) // a !== b >> > > >> !(a > b) // a <= b >> (!(a > b) && !(a == b)) // a < b >> > > I'm not sure this is
Re: const {resolve} = Promise; // fails
I'd reinforce this with the fact that this works for RSVP.js https://github.com/tildeio/rsvp.js/, and so the current behaviour is a potential breaking point if code is being converted to use native Promises. On Thu, 19 Jul 2018 at 12:56 Andrea Giammarchi wrote: > As quickly discussed on Twitter, it's very inconvenient and inconsistent > that the following fails: > > ```js > const {resolve, reject} = Promise; > > resolve(123); // throws > ``` > > Compared to every other public static method in ECMAScript that works, > including those methods that might need the contextual class, as it is for > the Array.from case. > > ```js > const {from} = Array; > > from({0: 'abc', length: 1}); // ["abc"] // all good > ``` > > Why cannot Promise methods fallback to Promise constructor when the > class/context is not available? > > Wouldn't be simple/reasonable change to make so that developers > expectations would be preserved? > > Best Regards. > ___ > 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
const {resolve} = Promise; // fails
As quickly discussed on Twitter, it's very inconvenient and inconsistent that the following fails: ```js const {resolve, reject} = Promise; resolve(123); // throws ``` Compared to every other public static method in ECMAScript that works, including those methods that might need the contextual class, as it is for the Array.from case. ```js const {from} = Array; from({0: 'abc', length: 1}); // ["abc"] // all good ``` Why cannot Promise methods fallback to Promise constructor when the class/context is not available? Wouldn't be simple/reasonable change to make so that developers expectations would be preserved? Best Regards. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Small Proposal "!in"
Although I support the idea of `!in` (for the same reasons as T.J. Crowder mentioned, plus it's useful for duck typing), what some browsers do isn't a great argument as modern browsers follow the spec more closely with regards to inherited accessors like this and you'd never be able to use `!in` for an older browser. However, you do have a point in that accessors can live anywhere in the prototype chain and an object's properties may not necessarily be 'owned' by the object in question: document.createElement('input').hasOwnProperty('type') // false So far, the main argument against has been that `hasOwnProperty()` is recommended over `in` as a more robust check. I don't see how this is a valid concern, they clearly have different use cases and you're not going to solve that problem be excluding a negated `in` from the spec (`!(a in b)` is still easier to type than `!b.hasOwnProperty(a)`). There are plenty of valid use cases for `in`, not least duck typing as mentioned before: function feed(duck) { if ('quackPitch' in duck && duck.canSwim) { duck.give(defrostedPeas); } } `!in` and `!instanceof` would be great additions to the operator sets. On Thu, 19 Jul 2018 at 12:06 Tobias Buschor wrote: > There are valid use-cases. > As an example, some browsers have "onfocus" as an own property of > "window", some as an inherited. > > ```js > if ('onfocus' !in window) { > // polyfill onfocus... > } > ``` > > > Am Mi., 18. Juli 2018 um 18:32 Uhr schrieb Mike Samuel < > mikesam...@gmail.com>: > >> >> >> On Wed, Jul 18, 2018 at 12:21 PM Michael Theriot < >> michael.lee.ther...@gmail.com> wrote: >> >>> I think it is irrelevant; the operator already exists and I would assume >>> if you want the negation of it you are using it correctly in the first >>> place. Otherwise are you not just arguing for its removal altogether? But >>> to answer your question one case that comes to mind is trapping get/has in >>> a proxy handler. >> >> >> Why should we assume that only people who consistently use `in` correctly >> would want the negation? It seems that people who use it incorrectly >> because they are confused about the precise semantics or don't care might >> want the negation too. If there are more of the latter then we should not >> assume what you assume. >> >> Proxy handler code is important, but very few developers will ever write >> a proxy handler over their careers, so this seems like a marginal use case. >> Besides, Reflect.has is probably a better choice in a proxy handler. >> >> I am not arguing for removing `in`. That would break the web. I am just >> arguing for prioritizing changes that provide features that more closely >> match the semantics developers typically want over making it more >> convenient to write code that seems to work in casual testing but has >> subtly wrong semantics. >> >> >> >> >> >> >> >>> On Wednesday, July 18, 2018, Mike Samuel wrote: >>> On Wed, Jul 18, 2018 at 11:05 AM Michael Theriot < michael.lee.ther...@gmail.com> wrote: > I think `in` and `instanceof` could both benefit from having negated > versions. > > Assuming the developer is using `in` correctly, hasOwnProperty > concerns are irrelevant. Either way they would attempt to use !(a in b), > not !hasOwnProperty. > Why should we assume the developer is using `in` correctly? Apologies if I buried my question at the end. It was, what are the use cases for `in` that would not be better served by an ergonomic, infix hasOwnProperty? Same reason we don't use... > !(a == b) // a != b > !(a === b) // a !== b > > !(a > b) // a <= b > (!(a > b) && !(a == b)) // a < b > I'm not sure this is relevant to your larger point, and I've already conceded ergonomics, but these last two are not equivalent because NaN is weird. a = NaN, b = 0 [!(a > b), a <= b] // [true, false] [!(a > b) && !(a == b), a < b] // [true, false] > On Thursday, June 28, 2018, Tobias Buschor > wrote: > >> I dont like to write: >> if ( !('x' in obj) && !('y' in obj) ) { >> doit() >> } >> >> I was even tempted to write it that way: >> if ('x' in obj || 'y' in obj) { } else { >> doit() >> } >> >> What about a !in operator to write it like this? >> if ('x' !in obj && 'y' !in obj) { >> doit() >> } >> >> ___ > 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 >> > > > -- > Freundliche Grüsse > Tobias Buschor > > schwups GmbH > Hauptstr. 33 > 9424 Rheineck/SG > > +41 76 321 23 21
Re: Small Proposal "!in"
There are valid use-cases. As an example, some browsers have "onfocus" as an own property of "window", some as an inherited. ```js if ('onfocus' !in window) { // polyfill onfocus... } ``` Am Mi., 18. Juli 2018 um 18:32 Uhr schrieb Mike Samuel : > > > On Wed, Jul 18, 2018 at 12:21 PM Michael Theriot < > michael.lee.ther...@gmail.com> wrote: > >> I think it is irrelevant; the operator already exists and I would assume >> if you want the negation of it you are using it correctly in the first >> place. Otherwise are you not just arguing for its removal altogether? But >> to answer your question one case that comes to mind is trapping get/has in >> a proxy handler. > > > Why should we assume that only people who consistently use `in` correctly > would want the negation? It seems that people who use it incorrectly > because they are confused about the precise semantics or don't care might > want the negation too. If there are more of the latter then we should not > assume what you assume. > > Proxy handler code is important, but very few developers will ever write a > proxy handler over their careers, so this seems like a marginal use case. > Besides, Reflect.has is probably a better choice in a proxy handler. > > I am not arguing for removing `in`. That would break the web. I am just > arguing for prioritizing changes that provide features that more closely > match the semantics developers typically want over making it more > convenient to write code that seems to work in casual testing but has > subtly wrong semantics. > > > > > > > >> On Wednesday, July 18, 2018, Mike Samuel wrote: >> >>> >>> >>> On Wed, Jul 18, 2018 at 11:05 AM Michael Theriot < >>> michael.lee.ther...@gmail.com> wrote: >>> I think `in` and `instanceof` could both benefit from having negated versions. Assuming the developer is using `in` correctly, hasOwnProperty concerns are irrelevant. Either way they would attempt to use !(a in b), not !hasOwnProperty. >>> >>> Why should we assume the developer is using `in` correctly? >>> Apologies if I buried my question at the end. It was, what are the use >>> cases for `in` that would not be better served by an ergonomic, infix >>> hasOwnProperty? >>> >>> >>> Same reason we don't use... !(a == b) // a != b !(a === b) // a !== b >>> >>> !(a > b) // a <= b (!(a > b) && !(a == b)) // a < b >>> >>> I'm not sure this is relevant to your larger point, and I've already >>> conceded ergonomics, but >>> these last two are not equivalent because NaN is weird. >>> >>> a = NaN, b = 0 >>> [!(a > b), a <= b] // [true, false] >>> [!(a > b) && !(a == b), a < b] // [true, false] >>> >>> >>> >>> >>> On Thursday, June 28, 2018, Tobias Buschor wrote: > I dont like to write: > if ( !('x' in obj) && !('y' in obj) ) { > doit() > } > > I was even tempted to write it that way: > if ('x' in obj || 'y' in obj) { } else { > doit() > } > > What about a !in operator to write it like this? > if ('x' !in obj && 'y' !in obj) { > doit() > } > > ___ 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 > -- Freundliche Grüsse Tobias Buschor schwups GmbH Hauptstr. 33 9424 Rheineck/SG +41 76 321 23 21 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Feature proposal
Yeah, i meant T.J. Crowder's comment that `reverseView` won't solve original issue. 2018-07-19 12:34 GMT+03:00 Isiah Meadows : > It shouldn't make anything that much more complex - the various Array > methods are already generic. > > > On Thu, Jul 19, 2018, 05:31 Dmitry Shulgin wrote: > >> Cool, gonna read it out. >> First impression -- it can make methods more complex and usage will be >> different between `find`, `findlastIndex` etc., if we want to use something >> like `reverseView`. >> >> >> 2018-07-19 11:56 GMT+03:00 T.J. Crowder >> : >> >>> On Thu, Jul 19, 2018 at 9:49 AM, Isiah Meadows >>> wrote: >>> > What about this alternate proposal: >>> >>> Great minds: https://esdiscuss.org/topic/fwd-feature-proposal#content-5 >>> ;-) >>> >>> -- T.J. Crowder >>> >> >> ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Feature proposal
Cool, gonna read it out. First impression -- it can make methods more complex and usage will be different between `find`, `findlastIndex` etc., if we want to use something like `reverseView`. 2018-07-19 11:56 GMT+03:00 T.J. Crowder : > On Thu, Jul 19, 2018 at 9:49 AM, Isiah Meadows > wrote: > > What about this alternate proposal: > > Great minds: https://esdiscuss.org/topic/fwd-feature-proposal#content-5 > ;-) > > -- T.J. Crowder > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Feature proposal
I'd rather keep it restricted to very simple, context-free things like a reverse subtract or single add, with only a few bits of data necessary. Anything more is going to be a perf concern because you can't avoid visible side effects. On Thu, Jul 19, 2018, 05:03 Michael Luder-Rosefield wrote: > This array view thing is very close to what I had in mind, and seems to > suggest to a lot of interesting possibilities. > > What strikes me as the two most significant are: > >- again, 'reversed' is just one alternative iteration order through, >though almost certainly the most useful >- others I can think of could be 'even/odd indexes', 'random shuffle', > 'iterate-until /while-condition', and filter equivalents >- as well as the view defining the iteration order, it could define >the computed value > - this would be basically a map where the value isn't computed > until accessed; caching behaviour could be user-determined > > > > > On Thu, 19 Jul 2018 at 09:49 Isiah Meadows wrote: > >> What about this alternate proposal: >> >> >> https://github.com/isiahmeadows/array-additions-proposal/blob/master/README.md#get-arrayprototypereversed-get-typedarrayprototypereversed >> >> (I've got a myriad of other related stuff there, too.) >> >> >> On Thu, Jul 19, 2018, 04:41 Dmitry Shulgin wrote: >> >>> Above we was talking about this. >>> consistency and handy using -- two main reasons for this proposal. >>> >>> `reverse` will also mutate my array, cause of in-place implementation. >>> >>> You can find workaround for many existing methods, but it's not handy to >>> my mind. >>> >> ___ >> 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: Feature proposal
This array view thing is very close to what I had in mind, and seems to suggest to a lot of interesting possibilities. What strikes me as the two most significant are: - again, 'reversed' is just one alternative iteration order through, though almost certainly the most useful - others I can think of could be 'even/odd indexes', 'random shuffle', 'iterate-until /while-condition', and filter equivalents - as well as the view defining the iteration order, it could define the computed value - this would be basically a map where the value isn't computed until accessed; caching behaviour could be user-determined On Thu, 19 Jul 2018 at 09:49 Isiah Meadows wrote: > What about this alternate proposal: > > > https://github.com/isiahmeadows/array-additions-proposal/blob/master/README.md#get-arrayprototypereversed-get-typedarrayprototypereversed > > (I've got a myriad of other related stuff there, too.) > > > On Thu, Jul 19, 2018, 04:41 Dmitry Shulgin wrote: > >> Above we was talking about this. >> consistency and handy using -- two main reasons for this proposal. >> >> `reverse` will also mutate my array, cause of in-place implementation. >> >> You can find workaround for many existing methods, but it's not handy to >> my mind. >> > ___ > 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: Feature proposal
On Thu, Jul 19, 2018 at 9:49 AM, Isiah Meadows wrote: > What about this alternate proposal: Great minds: https://esdiscuss.org/topic/fwd-feature-proposal#content-5 ;-) -- T.J. Crowder ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Feature proposal
What about this alternate proposal: https://github.com/isiahmeadows/array-additions-proposal/blob/master/README.md#get-arrayprototypereversed-get-typedarrayprototypereversed (I've got a myriad of other related stuff there, too.) On Thu, Jul 19, 2018, 04:41 Dmitry Shulgin wrote: > Above we was talking about this. > consistency and handy using -- two main reasons for this proposal. > > `reverse` will also mutate my array, cause of in-place implementation. > > You can find workaround for many existing methods, but it's not handy to > my mind. > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Feature proposal
Above we was talking about this. consistency and handy using -- two main reasons for this proposal. `reverse` will also mutate my array, cause of in-place implementation. You can find workaround for many existing methods, but it's not handy to my mind. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss