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