> What it's doesn't cover (and in my opinion should be the focus of a new > proposal) is Decorators for literal objects. Something like the code below is > yet not proposed: > > ``` js > const foo = { > @lazy bar: 3, > }; > ```
what would happen if you tried to JSON.stringify foo? a core-value of javascript to industry is as an idiot-proof/least-surprise language for serializing json-data across browser <-> server. junior-programmers who naively employ hard-to-serialize things like custom-getters in their low-level code, mostly end up annoying senior-programmers when they have to debug high-level integration-code that have problems baton-passing those states around. kai zhu kaizhu...@gmail.com > On 12 Jun 2018, at 9:07 PM, Isiah Meadows <isiahmead...@gmail.com> wrote: > > BTW, I proposed similar (lazy values) 9 months ago [1], and it's been > on the list plenty of times [2]. I'd personally *love* to see it > happen, but I find it not very likely it'd make it, especially as a > property (since decorators can rectify that). > > [1]: https://esdiscuss.org/topic/lazy-evaluation > [2]: > https://www.google.com/search?q=site%3Aesdiscuss.org+lazy+property+OR+getter+OR+setter > > ----- > > Isiah Meadows > m...@isiahmeadows.com > www.isiahmeadows.com > > > On Tue, Jun 12, 2018 at 8:48 AM, Andrea Giammarchi > <andrea.giammar...@gmail.com> wrote: >> FWIW, I think to keep it simple `lazy: true` would be enough for the time >> being. >> >> Having the new descriptor inside the descriptor seems a bit over engineering >> at this point, imo, but having a field already won't exclude, in the >> feature, the ability to improve that field (similar way addEventListener on >> DOM got promoted from `(type, handler, boolean)` signature to `(type, >> handler, boolean || options)`) >> >> I also agree that `lazy field = expr` is a different beast, and it won't >> play well with descriptors as we know, but it might allow overwrites if >> accessed directly. >> >> I wouldn't mind that as long as it plays well with objects and classes, and >> as long as there is an official way to lazy define properties, and if it >> could be so lazy that if redefined disappears, in that direct assignment >> form, it would be a solution to all my cases. >> >> Regards >> >> >> On Tue, Jun 12, 2018 at 2:37 PM, <he...@mailbox.sk> wrote: >>> >>> Actually, by malleable I meant only configurable:true, so one can change >>> it via Object.defineProp… api, I did not mean necessarily to define it as >>> value. >>> >>> I have no strong opinion on what should be there after the first access, >>> but it boils down on how will it be exposed via Object.defineProperty, >>> really, because as little as possible should be changed, IOW as much as >>> possible retained. >>> >>> So on case things are defined as (only pondering the property descriptor >>> here, the call is obvious): >>> >>> { lazy: true, get: () => Math.random() } … [1] >>> >>> or, bigger example: >>> >>> { lazy: { configurable: false }, enumerable: false, get: () => >>> foos.length, set: x => console.log(`set ${x}`) } … [2] >>> >>> Then what should be generated is indeed a getter so that setter may be >>> retained as well in [2]. >>> >>> If the definition is: >>> >>> { lazy: { configurable: false, writable: false, enumerable: true, compute: >>> () => Math.random() }, enumerable: false } … [3] >>> >>> then it defines a value (which is not enumerable until first accessed thus >>> created; contrived example, I know). >>> >>> This post also shows a proposal how to, in future proof way, define what >>> attributes will the replaced getter/value have: put it In lazy field of prop >>> descriptor, lazy: true means shortcut for “the default way / Inherit from >>> what is there now”. >>> >>> Herby >>> >>> On June 12, 2018 2:02:28 PM GMT+02:00, Aadit M Shah >>> <aaditms...@fastmail.fm> wrote: >>>> Okay, so my previous statement about field declarations in classes >>>> being >>>> invalid was incorrect. I didn't see Andrea's link to the class field >>>> declarations proposal[1]. Hence, from what I understand we're >>>> considering the following syntax: >>>> const zeros = { head: , lazy tail: this }; >>>> >>>> class Random { >>>> lazy value = Math.random(); >>>> } >>>> >>>> As for semantics, Herby's philosophy of "malleable unless specified >>>> otherwise" makes sense. Hence, the above code would be transpiled to: >>>> const zeros = { >>>> head: , >>>> get tail() { >>>> return Object.defineProperty(this, "tail", { >>>> value: this >>>> }).tail; >>>> } >>>> }; >>>> >>>> class Random { >>>> get value() { >>>> return Object.defineProperty(this, "value", { >>>> value: Math.random() >>>> }).value; >>>> } >>>> } >>>> >>>> I guess we'd also be adopting the syntax for private fields and static >>>> fields? For example, lazy #value and lazy static #value? >>>> >>>> On Tue, Jun 12, 2018, at 7:32 AM, he...@mailbox.sk wrote: >>>>> >>>>> >>>>> On June 12, 2018 11:32:22 AM GMT+02:00, Aadit M Shah >>>>> <aaditms...@fastmail.fm> wrote:>> Actually, from a parsing >>>> perspective I believe it shouldn't be too >>>>>> difficult to implement the `lazy name: expression` syntax. In >>>>>> addition, I'm not too keen on your `lazy name() { return >>>> expression;>> }` syntax because: >>>>>> 1. It's more verbose. >>>>>> 2. It seems to me that it's no different than creating a regular >>>>>> getter: >>>>>> >>>>>> const take = (n, xs) => n === ? null : xs && { head: xs.head, >>>>>> get >>>>>> tail() { const value = take(n - 1, xs.tail); >>>>>> Object.defineProperty(this, "tail", { configurable: >>>> false,>> get: () => value }); return value; } }; >>>>> >>>>> I am pretty sure Andrea mixed syntax of lazy getter with its >>>>> implementation for brevity, and the actual lazy getter would >>>>> look like:> >>>>> lazy tail() { return take(n - 1, xs.tail); } >>>>> >>>>>> Regarding the second bullet point, I've probably misunderstood >>>>>> what you>> were trying to convey. Perhaps you could elucidate. >>>>>> Anyway, making the property non-configurable after accessing it >>>> seems>> like a reasonable thing to do. >>>>> >>>>> Here I disagree. No syntax construct so far forces immutability. The >>>>> get x() / set x() ones are configurable. If you defined lazy getter >>>>> so far by get(), you could have changed it using >>>>> Object.defineProperties if there was some strange need for it. You >>>>> had to explicitly freeze etc. or defineProperty with configurable >>>>> false if you wanted to make it so.> >>>>> This autofreezing if the value sticks out out this philosophy of " >>>>> malleable unless specified otherwise".> >>>>>> >>>>>> On Tue, Jun 12, 2018, at 3:44 AM, Andrea Giammarchi wrote: >>>>>>> My 2 cents, >>>>>>> I use lazy getters since about ever and I'd love to have such >>>>>> syntax >>>>>>> in place but I think there is room for some improvement / >>>>>>> simplification in terms of syntax.> >>>>>>> *## Keep it get*ish** >>>>>>> >>>>>>> From parsing perspective, introducing `lazy tail()` seems way >>>>>>> simpler>>> than introducing `lazy tail:` for the simple reason that >>>> everything>>> that can parse `get tail()` and `set tail()` is in place >>>> already in>>> every engine. I don't write them but I'm sure having an >>>> extra >>>>>> keyboard >>>>>>> to catch shouldn't be crazy complicated.> >>>>>>> *## class compatible* >>>>>>> >>>>>>> because you used `delete this.tail` and mentioned functional >>>>>>> programming, I'd like to underline ES doesn't force anyone to one >>>>>>> programming style or another. That means new syntax should play >>>>>> nicely >>>>>>> with classes too, and in this case the proposal doesn't seem to >>>>>>> address that because of the direct value mutation, as generic >>>>>>> property, and the removal of that property from the object, >>>>>>> something>>> not needed if inherited.> >>>>>>> My variant would do the same, except it would keep the value an >>>>>>> accessor:> >>>>>>> ```js >>>>>>> const take = (n, xs) => n === 0 ? null : xs && { >>>>>>> head: xs.head, >>>>>>> lazy tail() { >>>>>>> return Object.defineProperty(this, 'tail', { >>>>>>> configurable: false, >>>>>>> get: (value => >>>>>>> // still a getter >>>>>>> () => value >>>>>>> )( >>>>>>> // executed once >>>>>>> take(n - 1, xs.tail) >>>>>>> ) >>>>>>> }).tail; >>>>>>> } >>>>>>> }; >>>>>>> ``` >>>>>>> >>>>>>> This would keep initial accessor configuration, in terms of >>>>>>> enumerability, but it will freeze its value forever and, on top of >>>>>>> that, this will play already well with current valid ES2015 >>>>>>> classes syntax.> >>>>>>> I also believe myself proposed something similar a while ago (or >>>>>>> somebody else and I agreed with that proposal) but for some >>>>>>> reason it>>> never landed.> >>>>>>> Hopefully this time the outcome would be different. >>>>>>> >>>>>>> Best Regards >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> On Tue, Jun 12, 2018 at 9:13 AM, Aadit M Shah >>>>>>> <aaditms...@fastmail.fm> wrote:>> __ >>>>>>>> Hello TC39, >>>>>>>> >>>>>>>> I recently opened an issue[1] in the tc39/ecma262[2] repository, >>>>>>>> proposing a new syntax for lazy getters, and I was directed to >>>> the>>>> CONTRIBUTING[3] page which stated that I should start a >>>>>>>> conversation>>>> on this mailing list.>> >>>>>>>> So, my feature proposal is to have syntactic sugar for >>>>>>>> creating lazy>>>> getters[4]. To summarize my original proposal >>>> (which you can >>>>>>>> read by>>>> following the very first link above), I find that >>>> creating lazy >>>>>>>> getters is very verbose. For example, consider:>> >>>>>>>> const take = (n, xs) => n === ? null : xs && { >>>>>>>> head: xs.head, >>>>>>>> get tail() { >>>>>>>> delete this.tail; >>>>>>>> return this.tail = take(n - 1, xs.tail); >>>>>>>> } >>>>>>>> }; >>>>>>>> >>>>>>>> My proposed solution is to add a new keyword lazy to the >>>> language.>>>> This keyword can only be used as a prefix to longhand >>>> property >>>>>>>> names>>>> in object initializers, and it defers the execution of >>>> the value >>>>>>>> expression until the property is accessed. In short, it's just >>>>>>>> syntactic sugar for lazy getters:>> >>>>>>>> const take = (n, xs) => n === ? null : xs && { >>>>>>>> head: xs.head, >>>>>>>> lazy tail: take(n - 1, xs.tail) >>>>>>>> }; >>>>>>>> >>>>>>>> This is purely syntactic sugar. The semantics of this new syntax >>>>>>>> would remain the same as that of the desugared syntax. In >>>>>> particular, >>>>>>>> calling Object.getOwnPropertyDescriptor(list, "tail") would >>>> return>> an >>>>>>>> accessor descriptor before accessing list.tail and a data >>>>>>>> descriptor>>>> afterwards.>> >>>>>>>> Furthermore, there are other advantages of having this syntactic >>>>>>>> sugar. For example, creating cyclic data structures becomes much >>>>>>>> easier. Examples are provided in my original proposal which is >>>>>> linked >>>>>>>> above. Hope to hear your thoughts on this.>> >>>>>>>> Regards, >>>>>>>> Aadit M Shah >>>>>>>> >>>>>>>> _________________________________________________ >>>>>>>> es-discuss mailing list >>>>>>>> es-discuss@mozilla.org >>>>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>>>>> >>>>>> >>>>>> >>>>>> Links: >>>>>> >>>>>> 1. https://github.com/tc39/ecma262/issues/1223 >>>>>> 2. https://github.com/tc39/ecma262 >>>>>> 3. https://github.com/tc39/ecma262/blob/master/CONTRIBUTING.md >>>>>> 4. >>>>>> >>> >>>>> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get#Smart_self-overwriting_lazy_getters >>>> >>>> Links: >>>> >>>> 1. https://github.com/tc39/proposal-class-fields#field-declarations >> >> >> >> _______________________________________________ >> 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