[Proposal] New syntax for lazy getters

Andrea Giammarchi andrea.giammarchi at gmail.com
Tue Jun 12 12:32:03 UTC 2018


forgot about this:

> I think {get: getterFn, lazy: true, …} could work.

sort of, because descriptors can be only for properties or accessors, but
lazy + set, as accessor might look weird.

However, if I can dare bringing in another use case I have daily in my
code, I have a case for having a setter that defines the getter if
explicit, so that by default I have a lazy getter, but if before it gets
used somebody sets the property, it overrides the lazy getter.

This might happen, as example, during constructor time, as opposite of
after initialization.

Example:

```js
class Weirdo {
  constructor(theThing = null) {
    if (theThing != null) {
      this.theThing = theThing;
    }
  }
  get theThing() {
    const value = doVeryExpensiveThing();
    Object.defineProperty(this, 'theThing', {
      get: () => value
    });
    return value;
  }
  set theThing(value) {
    Object.defineProperty(this, 'theThing', {
      get: () => value
    });
  }
}
```

Honestly, I don't see why this would create any issue with the accessor
descriptor, so that I can `lazy theThing() { return
doVeryExpensiveThing(); }` and eventually provide a `set theThing() {}` to
do whatever I want to do when, and if, needed.

So yes, if `lazy: true` plays well with accessors, and it's to define the
special `get` behavior only, then it's a valid welcome, and nice to have
addition.

```js
Object.defineProperty(
  test,
  'random',
  {
    configurable: false, // by default
    enumerable: false, // by default
    lazy: false, // by default
    get() { return this.x + Math.random(); },
    set() { /* optional, do whatever */ }
  }
);
```

My last question / concern at this point, in case descriptors should be
part of this proposal, is how to retrieve the initial lazy descriptor from
an object which lazy getter overwrote such value, but I also think this
should not be a real-world concern or, eventually, a must know caveat for
functional programmers that play procedurally with accessors.

I think I've exposed all my thoughts on this issue, I'll hope for some
extra outcome.

Best Regards


On Tue, Jun 12, 2018 at 1:14 PM, <herby at mailbox.sk> wrote:

>
>
> On June 12, 2018 9:44:31 AM GMT+02:00, Andrea Giammarchi <
> andrea.giammarchi at gmail.com> 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.
>
> Yeah I find this better.
>
> Also fixes the this questions by unambiguously setting it to the instance.
>
> >*## Keep it getish*
> >
> >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,
>
> Why enforcing configurable false? When you use get x() / set x() syntax,
> it leaves the thing configurable true. I feel it is more consistent to have
> the replaced getter copy configurable from existing status quo, that is,
> what is actual configurable of this.tail.
>
> And of course, Object.defineProperty family needs a way to create this, I
> think {get: getterFn, lazy: true, …} could work.
>
> Herby
>
> >        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.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20180612/f3f999f5/attachment-0001.html>


More information about the es-discuss mailing list