Re: [Proposal] New syntax for lazy getters

2018-06-29 Thread Isiah Meadows
FWIW, individual parts of the "grid" don't all have to ship at the
same time. Private instance fields are farther along than private
static fields, for instance, and private methods are being considered
separately from private fields. Another example is with async
functions beating async generators/iterators and generator arrow
functions being stage 1 while everything else in the function "grid"
has a generator variant. And of course, the `export foo from
"..."`/`export * as foo from "..."` proposals filling out that "grid".

And as for the decorators proposal itself, it's been sharply delayed
from having its entire data model redone multiple times over the
course of several months (according to their meeting notes). I don't
think this requires nearly as much consideration as private fields,
etc.

-

Isiah Meadows
m...@isiahmeadows.com
www.isiahmeadows.com


On Thu, Jun 28, 2018 at 2:24 AM, Augusto Moura
 wrote:
> *An errata in my code*
> The getter is mutating the object with a enumerable property, so
> consecutives invocations of JSON.stringify will result different from
> the first call (if the property is yet not initialized). The current
> problem is:
> ```js
> JSON.stringify(foo) // Returns "{"bar":3}"
> // After the first bar "get" the object has now another property "_bar"
> JSON.stringify(foo) // Returns "{"bar":3,"_bar":3}"
> ```
> I did it as a quick loose scratch and didn't test it. A more robust
> implementation (with a helper function) probably would use closures to
> maintain the factory state. As exemplified:
> ```js
> const defineLazyProp = (obj, propName, valueFactory) => {
>   let selfDestroyingFactory = () => {
> const value = valueFactory();
> selfDestroyingFactory = () => value;
> return value;
>   };
>
>   return Object.defineProperty(obj, propName, {
> enumerable: true,
> configurable: false, // It might be discussed if the lazy prop
> should be configurable or not
> get() {
>   return selfDestroyingFactory();
> },
>   });
> };
>
> const foo = {};
>
> defineLazyProp(foo, 'bar', () => 3);
>
> // This should work correctly now
> console.log(JSON.stringify(foo));
> console.log(JSON.stringify(foo));
> ```
> It's a bit more verbose, but it's the best way I can think of
> "ponyfilling" it at the moment.
>
> On June 28, 02:45, Isiah Meadows  wrote:
>>
>> I agree the main proposal is long and complex, but this kind of addition 
>> could be designed with little effort to "fall out of the grid", since it has 
>> so much in common with classes already (properties, getters/setters, 
>> methods). The main question is with properties, but those are easy to just 
>> leave out, since function calls do just as well.
>>
>
> You are right, but yet I prefer to get the classes decorators
> advancing to a greater stage as soon as possible, a objet literal
> decorator would be a easy extension to the current proposal. By the
> way, I was comparing with the 2 others proposals by the fact that they
> are more like "extensions" to the main proposal, not by the complexity
> (as far as I know, mix the 3 decorators proposals in one would stall
> most of the work), but yeah they really are different beasts.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] New syntax for lazy getters

2018-06-28 Thread Augusto Moura
*An errata in my code*
The getter is mutating the object with a enumerable property, so
consecutives invocations of JSON.stringify will result different from
the first call (if the property is yet not initialized). The current
problem is:
```js
JSON.stringify(foo) // Returns "{"bar":3}"
// After the first bar "get" the object has now another property "_bar"
JSON.stringify(foo) // Returns "{"bar":3,"_bar":3}"
```
I did it as a quick loose scratch and didn't test it. A more robust
implementation (with a helper function) probably would use closures to
maintain the factory state. As exemplified:
```js
const defineLazyProp = (obj, propName, valueFactory) => {
  let selfDestroyingFactory = () => {
const value = valueFactory();
selfDestroyingFactory = () => value;
return value;
  };

  return Object.defineProperty(obj, propName, {
enumerable: true,
configurable: false, // It might be discussed if the lazy prop
should be configurable or not
get() {
  return selfDestroyingFactory();
},
  });
};

const foo = {};

defineLazyProp(foo, 'bar', () => 3);

// This should work correctly now
console.log(JSON.stringify(foo));
console.log(JSON.stringify(foo));
```
It's a bit more verbose, but it's the best way I can think of
"ponyfilling" it at the moment.

On June 28, 02:45, Isiah Meadows  wrote:
>
> I agree the main proposal is long and complex, but this kind of addition 
> could be designed with little effort to "fall out of the grid", since it has 
> so much in common with classes already (properties, getters/setters, 
> methods). The main question is with properties, but those are easy to just 
> leave out, since function calls do just as well.
>

You are right, but yet I prefer to get the classes decorators
advancing to a greater stage as soon as possible, a objet literal
decorator would be a easy extension to the current proposal. By the
way, I was comparing with the 2 others proposals by the fact that they
are more like "extensions" to the main proposal, not by the complexity
(as far as I know, mix the 3 decorators proposals in one would stall
most of the work), but yeah they really are different beasts.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] New syntax for lazy getters

2018-06-27 Thread Isiah Meadows
I agree the main proposal is long and complex, but this kind of addition
could be designed with little effort to "fall out of the grid", since it
has so much in common with classes already (properties, getters/setters,
methods). The main question is with properties, but those are easy to just
leave out, since function calls do just as well.

Function declaration/expression/parameter decorators are completely
different beasts with little in common, so I feel it's a bad comparison.

On Thu, Jun 28, 2018, 01:33 Augusto Moura  wrote:

> On June 27, 2018 09:23, kai zhu  wrote:
> > 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.
>
> Depends on the chosen implementation (which will be open for discussion
> for sure). The Groovy AST transformation annotation `@Lazy` for example
> translates the field into a getter (without a setter, making it virtually a
> readonly field) which initializes the field once at the first invocation
> (there is a example of the generated code at Groovy docs[1]). If we follow
> this path we can easily implement it in Javascript as a enumerable get
> property descriptor. About `JSON.stringify`, it renders all enumerable
> properties of a object, including getters, so it will initialize the field
> and represent it as any other property. My previous decorator example could
> be loosely interpreted as:
>
> ```js
> const foo = {
>   get bar() {
> if (!this.hasOwnProperty('_bar')) {
>   this._bar = 3;
> }
> return this._bar;
>   },
> };
>
> // JSON.stringify would write the correct bar value, initalizing it if
> necessary
> JSON.stringify(foo) // "{"bar":3}"
> ```
>
> We could make a setter too, but the logic to implement it it's a lot more
> complex and subject to confusion
>
> On June 27, 2018 10:11, Isiah Meadows  wrote:
> > If you're wanting to propose new places for decorators, you'd have much
> better luck here: https://github.com/tc39/proposal-decorators
>
> I think that the main proposal is already long and complex, maybe it's a
> better idea to finalize it first and then start a new proposal about this
> others decorators places (as with function expression decorators and
> function parameters decoratos).
>
> [1] http://groovy-lang.org/metaprogramming.html#xform-Lazy
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] New syntax for lazy getters

2018-06-27 Thread Augusto Moura
On June 27, 2018 09:23, kai zhu  wrote:
> 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.

Depends on the chosen implementation (which will be open for discussion for
sure). The Groovy AST transformation annotation `@Lazy` for example
translates the field into a getter (without a setter, making it virtually a
readonly field) which initializes the field once at the first invocation
(there is a example of the generated code at Groovy docs[1]). If we follow
this path we can easily implement it in Javascript as a enumerable get
property descriptor. About `JSON.stringify`, it renders all enumerable
properties of a object, including getters, so it will initialize the field
and represent it as any other property. My previous decorator example could
be loosely interpreted as:

```js
const foo = {
  get bar() {
if (!this.hasOwnProperty('_bar')) {
  this._bar = 3;
}
return this._bar;
  },
};

// JSON.stringify would write the correct bar value, initalizing it if
necessary
JSON.stringify(foo) // "{"bar":3}"
```

We could make a setter too, but the logic to implement it it's a lot more
complex and subject to confusion

On June 27, 2018 10:11, Isiah Meadows  wrote:
> If you're wanting to propose new places for decorators, you'd have much
better luck here: https://github.com/tc39/proposal-decorators

I think that the main proposal is already long and complex, maybe it's a
better idea to finalize it first and then start a new proposal about this
others decorators places (as with function expression decorators and
function parameters decoratos).

[1] http://groovy-lang.org/metaprogramming.html#xform-Lazy
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] New syntax for lazy getters

2018-06-27 Thread Isiah Meadows
If you're wanting to propose new places for decorators, you'd have much
better luck here: https://github.com/tc39/proposal-decorators

I do agree this is an obvious place for a decorator, and it is probably the
ideal way of specifying it for object properties, but your larger proposal
of adding decorators for objects would have better luck there.

-

Isiah Meadows
m...@isiahmeadows.com
www.isiahmeadows.com

On Wed, Jun 27, 2018 at 8:23 AM, kai zhu  wrote:

> 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  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
>  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,  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
>  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 

Re: [Proposal] New syntax for lazy getters

2018-06-27 Thread kai zhu
> 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  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
>  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,  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
>>>  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
>  wrote:>> Actually, 

Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Isiah Meadows
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
 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,  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
>>  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
>> >>  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 

Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Michał Wadas
Yes, something is getting done about decorators.
https://github.com/tc39/agendas/pull/398

On Tue, Jun 12, 2018 at 4:27 PM, Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> To me decorators are the answer to pretty much everything but for the last
> year I've seen zero progress on what seems to be a forever Stage 2
> proposal: https://github.com/tc39/proposals#stage-2
>
> Is there anything anyone can do to speed up adoption/implementation of
> that proposal?
>
> On Tue, Jun 12, 2018 at 4:24 PM, Augusto Moura 
> wrote:
>
>> I don't think a new keyword is the right path here. For classes lazy
>> fields can easily be implemented via decorators in the last proposal[1]
>> (also, Groovy has previous work implementing a `@Lazy` annotation[2] with
>> AST transformations for the same use case). In code something like:
>> ``` js
>> const lazy = (fieldMetadata) => {
>>   // change the field value in descriptor to a lazy factory
>> };
>>
>> class Foo {
>>
>>   @lazy bar = slowCalculation();
>>
>>   @lazy statements = (() => {
>>  if (this.bar > 0) {
>>return fooify();
>>  } else {
>>return barify();
>>  }
>>   }());
>>
>> }
>> ```
>>
>> 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,
>> };
>> ```
>>
>> I didn't made a deep search in ESDiscuss history but I remember this
>> feature being mentioned sometime ago.
>>
>> [1]: https://github.com/tc39/proposal-decorators
>> [2]: http://groovy-lang.org/metaprogramming.html#xform-Lazy
>> --
>> Augusto Moura
>>
>> ___
>> 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: [Proposal] New syntax for lazy getters

2018-06-12 Thread Andrea Giammarchi
To me decorators are the answer to pretty much everything but for the last
year I've seen zero progress on what seems to be a forever Stage 2
proposal: https://github.com/tc39/proposals#stage-2

Is there anything anyone can do to speed up adoption/implementation of that
proposal?

On Tue, Jun 12, 2018 at 4:24 PM, Augusto Moura 
wrote:

> I don't think a new keyword is the right path here. For classes lazy
> fields can easily be implemented via decorators in the last proposal[1]
> (also, Groovy has previous work implementing a `@Lazy` annotation[2] with
> AST transformations for the same use case). In code something like:
> ``` js
> const lazy = (fieldMetadata) => {
>   // change the field value in descriptor to a lazy factory
> };
>
> class Foo {
>
>   @lazy bar = slowCalculation();
>
>   @lazy statements = (() => {
>  if (this.bar > 0) {
>return fooify();
>  } else {
>return barify();
>  }
>   }());
>
> }
> ```
>
> 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,
> };
> ```
>
> I didn't made a deep search in ESDiscuss history but I remember this
> feature being mentioned sometime ago.
>
> [1]: https://github.com/tc39/proposal-decorators
> [2]: http://groovy-lang.org/metaprogramming.html#xform-Lazy
> --
> Augusto Moura
>
> ___
> 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: [Proposal] New syntax for lazy getters

2018-06-12 Thread Augusto Moura
I don't think a new keyword is the right path here. For classes lazy fields
can easily be implemented via decorators in the last proposal[1] (also,
Groovy has previous work implementing a `@Lazy` annotation[2] with AST
transformations for the same use case). In code something like:
``` js
const lazy = (fieldMetadata) => {
  // change the field value in descriptor to a lazy factory
};

class Foo {

  @lazy bar = slowCalculation();

  @lazy statements = (() => {
 if (this.bar > 0) {
   return fooify();
 } else {
   return barify();
 }
  }());

}
```

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,
};
```

I didn't made a deep search in ESDiscuss history but I remember this
feature being mentioned sometime ago.

[1]: https://github.com/tc39/proposal-decorators
[2]: http://groovy-lang.org/metaprogramming.html#xform-Lazy
-- 
Augusto Moura
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Herbert Vojčík
The problem here is that if lazy field and lazy getter are indeed 
different beast, one should be able to discriminate the two inside the 
property descriptor.


So maybe

  // replaces with getter on first access
  {lazy: producerFn, get: null, ...}

  // replaces with value on first access
  {lazy: producerFn, value: null, ...}

and in case both get and value are present, just be consistent with what 
is the behaviour now (early error or preferences of one over the other).


Herby

Andrea Giammarchi wrote on 12. 6. 2018 14:48:
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, > 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
mailto: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
 >> mailto: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 

Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Andrea Giammarchi
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,  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
> >>  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 

Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread herby


On June 12, 2018 2:37:05 PM GMT+02:00, 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.

Not to create a confusion, I _do_not_ propose that both ways be working, what I 
wanted to say is that only o e should be chosen, and that will select what will 
be there as a replacement.

Though, now that I think about it,

  lazy field = expr;

and

  lazy getter() { return expr; }

are different beasts.

Anyway, as Andrea said, enough said for the moment.

>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
> 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
>>>  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()` 

Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread herby
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  
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
>>  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 

Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Andrea Giammarchi
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,  wrote:

>
>
> On June 12, 2018 9:44:31 AM GMT+02:00, Andrea Giammarchi <
> andrea.giammar...@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.
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread T.J. Crowder
On Tue, Jun 12, 2018 at 12:31 PM, Aadit M Shah 
wrote:
> Classes in JavaScript don't allow assignments within the class body.
Hence,
> the following code is invalid:
>
> class Test {
> x = 123; // This throws an error.
> lazy random = this.x + Math.random(); // Similarly, this should be
> invalid.
> }

Andrea was using syntax from the [class fields proposal][1], currently at
Stage 3 and fairly commonly used via transpilation (he said "class fields"
later in the post, but didn't emphasize it).

-- T.J. Crowder

[1]: https://github.com/tc39/proposal-class-fields
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread herby



On June 12, 2018 1:32:04 PM GMT+02:00, he...@mailbox.sk wrote:
>This autofreezing if the value sticks out out this philosophy of "

_of_ the value

>malleable unless specified otherwise".
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Aadit M Shah
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
>  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
>>>  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.>>

Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Andrea Giammarchi
> Why enforcing configurable false?

The fact the lazy getter is called getter, and the fact that a getter
cannot be assigned or the engine throws errors, as opposite of a non
configurable property that will silently ignore the assignment, makes me
think substituting a lazy getter with a fixed getter is the way to.

But I also think being lazy, usually meaning with expensive computations
needed once only, it's a nice to have, and clean guard, to fix that getter
forever.

However, that creates observability of the getter, through its own property
descriptor, but also, as a getter, it might signal side effects, while a
fixed property on the object set as value would indicate there are,
probably, no side effects in accessing it.

TL;DR I'm not fully sure about the getter should be defined, if through its
inherited definition but with a different get callback that returns the
computed value, and only when it comes to classes, or through its own
property accessor, when it comes to objects.

Maybe this is the best way to go though, so that the following code:

```js
const test = {
  x: 123,
  lazy random() {
return this.x + Math.random();
  }
};

class Test {
  x = 123;
  lazy random() {
return this.x + Math.random();
  }
}
```

would de-sugar in something like this:

```js
const getDescriptor = (o, k) => (
  o ? (
Object.getOwnPropertyDescriptor(o, k) ||
getDescriptor(Object.getPrototypeOf(o), k)
  ) : o
);

const test = {
  x: 123,
  get random() {
const desc = getDescriptor(this, 'random');
const value = (function () {
  return this.x + Math.random();
}).call(this);
desc.get = () => value;
Object.defineProperty(this, 'random', desc);
return value;
  }
};

class Test {
  x = 123;
  get random() {
const desc = getDescriptor(this, 'random');
const value = (function () {
  return this.x + Math.random();
}).call(this);
desc.get = () => value;
Object.defineProperty(this, 'random', desc);
return value;
  }
}
```

preserving whatever behavior previously defined.



On Tue, Jun 12, 2018 at 1:14 PM,  wrote:

>
>
> On June 12, 2018 9:44:31 AM GMT+02:00, Andrea Giammarchi <
> andrea.giammar...@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.
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread herby



On June 12, 2018 11:32:22 AM GMT+02:00, Aadit M Shah  
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
>>  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 

Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Aadit M Shah
Classes in JavaScript don't allow assignments within the class body.
Hence, the following code is invalid:
class Test {
x = 123; // This throws an error.
lazy random = this.x + Math.random(); // Similarly, this should
be invalid.}

Hence, the more I think about it the more it makes sense to use the
following syntax instead:
const zeros = { head: , lazy tail() { return this; } };

class Random {
lazy random() { return Math.random(); }
}

const x = new Random;
const y = new Random;

console.log(x.value === x.value); // true
console.log(x.value === y.value); // false (in all probability)

It's more verbose than my initial proposal. However, as Andrea mentioned
it's consistent with the class method syntax and the this keyword can be
used within the lazy getter without causing confusion.
Finally, I think that `lazy () {  }` should be syntactic
sugar for:
get name() {
return Object.defineProperty(this, "", {
value: (function () {  }()),
configurable: false // Making it non-configurable is debatable.
}).;
}

Using Object.defineProperty instead of simple assignment will ensure
that it works in strict mode. In addition, it'll make the property non-
writable which is the behavior we want because it's non-writable before
memoization too, since it doesn't have a setter.

On Tue, Jun 12, 2018, at 5:52 AM, Andrea Giammarchi wrote:
> Actually, never mind. I've just realized this would work as well, and
> it's clean enough.> 
> ```js
> class Test {
>   x = 123;
>   lazy random = this.x + Math.random();
> }
> 
> const test = {
>   x: 123,
>   lazy random: this.x + Math.random()
> };
> ```
> 
> My only concern is if that class method is created N times per each
> instance (one of the reasons I use lazy getters in classes prototypes
> instead of per object) as it is AFAIK for current class fields if you
> attach an arrow function, instead of once per class, which seems to be
> preferable in a class context.> 
> Otherwise, I'd be happy to see that happen.
> 
> Best Regards
> 
> 
> 
> On Tue, Jun 12, 2018 at 11:44 AM, Andrea Giammarchi
>  wrote:>> it's not about being difficult, it's 
> about compatibility with
>> classes, where getters are OK since ever. However, since classes
>> fields are in Stage 3 [1] maybe it's OK to have:>> 
>> ```js
>> class Test {
>>   x = 123;
>>   lazy random = () => this.x + Math.random();
>> }
>> ```
>> 
>> However, like you've noticed, while it's easy to reason about the
>> context within a class declaration, it's easy to create a footgun
>> outside that.>> 
>> ```js
>> const test = {
>>   x: 123,
>>   lazy random: () => this.x + Math.random()
>> };
>> ```
>> 
>> That is a whole new meaning of arrow function I'd rather like not to
>> ever encounter.>> 
>> So what about extra new syntax?
>> 
>> ```js
>> class Test {
>>   x = 123;
>>   lazy random() => this.x + Math.random();
>> }
>> 
>> const test = {
>>   x: 123,
>>   lazy random() => this.x + Math.random()
>> };
>> ```
>> 
>> But I'm pretty sure at methods shorthand discussions that came up and
>> for some reason didn't work.>> 
>> 
>> 
>> [1] https://github.com/tc39/proposal-class-fields#field-declarations>> 
>> On Tue, Jun 12, 2018 at 11:32 AM, Aadit M Shah
>>  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; } };>>> 
>>> 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.>>> 
>>> 
>>> 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
 

Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread herby


On June 12, 2018 9:44:31 AM GMT+02:00, 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.

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.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Andrea Giammarchi
Actually, never mind. I've just realized this would work as well, and it's
clean enough.

```js
class Test {
  x = 123;
  lazy random = this.x + Math.random();
}

const test = {
  x: 123,
  lazy random: this.x + Math.random()
};
```

My only concern is if that class method is created N times per each
instance (one of the reasons I use lazy getters in classes prototypes
instead of per object) as it is AFAIK for current class fields if you
attach an arrow function, instead of once per class, which seems to be
preferable in a class context.

Otherwise, I'd be happy to see that happen.

Best Regards



On Tue, Jun 12, 2018 at 11:44 AM, Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> it's not about being difficult, it's about compatibility with classes,
> where getters are OK since ever. However, since classes fields are in Stage
> 3 [1] maybe it's OK to have:
>
> ```js
> class Test {
>   x = 123;
>   lazy random = () => this.x + Math.random();
> }
> ```
>
> However, like you've noticed, while it's easy to reason about the context
> within a class declaration, it's easy to create a footgun outside that.
>
> ```js
> const test = {
>   x: 123,
>   lazy random: () => this.x + Math.random()
> };
> ```
>
> That is a whole new meaning of arrow function I'd rather like not to ever
> encounter.
>
> So what about extra new syntax?
>
> ```js
> class Test {
>   x = 123;
>   lazy random() => this.x + Math.random();
> }
>
> const test = {
>   x: 123,
>   lazy random() => this.x + Math.random()
> };
> ```
>
> But I'm pretty sure at methods shorthand discussions that came up and for
> some reason didn't work.
>
>
>
> [1] https://github.com/tc39/proposal-class-fields#field-declarations
>
> On Tue, Jun 12, 2018 at 11:32 AM, Aadit M Shah 
> 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 === 0 ? null : xs && {
>>head: xs.head,
>>get tail() {
>>const value = take(n - 1, xs.tail);
>>Object.defineProperty(this, "tail", {
>>configurable: false,
>>get: () => value
>>});
>>return value;
>>}
>>};
>>
>>
>> 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.
>>
>>
>> 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 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,
>> 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 
>> wrote:
>>
>>
>> Hello TC39,
>>
>> I recently opened an issue  in
>> the tc39/ecma262  repository, proposing
>> a new 

Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Andrea Giammarchi
it's not about being difficult, it's about compatibility with classes,
where getters are OK since ever. However, since classes fields are in Stage
3 [1] maybe it's OK to have:

```js
class Test {
  x = 123;
  lazy random = () => this.x + Math.random();
}
```

However, like you've noticed, while it's easy to reason about the context
within a class declaration, it's easy to create a footgun outside that.

```js
const test = {
  x: 123,
  lazy random: () => this.x + Math.random()
};
```

That is a whole new meaning of arrow function I'd rather like not to ever
encounter.

So what about extra new syntax?

```js
class Test {
  x = 123;
  lazy random() => this.x + Math.random();
}

const test = {
  x: 123,
  lazy random() => this.x + Math.random()
};
```

But I'm pretty sure at methods shorthand discussions that came up and for
some reason didn't work.



[1] https://github.com/tc39/proposal-class-fields#field-declarations

On Tue, Jun 12, 2018 at 11:32 AM, Aadit M Shah 
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 === 0 ? null : xs && {
>head: xs.head,
>get tail() {
>const value = take(n - 1, xs.tail);
>Object.defineProperty(this, "tail", {
>configurable: false,
>get: () => value
>});
>return value;
>}
>};
>
>
> 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.
>
>
> 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 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,
> 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 
> wrote:
>
>
> Hello TC39,
>
> I recently opened an issue  in
> the tc39/ecma262  repository, proposing
> a new syntax for lazy getters, and I was directed to the CONTRIBUTING
>  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
> .
> 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 === 0 ? 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 

Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Aadit M Shah
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;} };
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.

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
>  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. 

Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Andrea Giammarchi
That is why I'm proposing to use a getter, you don't have to reason about
the context in `lazy fullname() { return this.firstName + ' ' +
this.lastName; }` and it still works with de-contextualized invokes such
`lazy random: () => Math.random()` as long as you transpile that as getter
calling the right context (when/if needed).

Both cases can de-sugar to same redefinition of a getter.

Regards


On Tue, Jun 12, 2018 at 10:56 AM, Aadit M Shah 
wrote:

> When the getter lives on a prototype it would install the memoized value
> on this using [[Define]]. This is the same way it would work in regular
> lazy getters:
>
> const defclass = prototype => {
> const constructor = prototype.constructor;
> constructor.prototype = prototype;
> return constructor;
> };
>
> const Person = defclass({
> constructor: function Person(firstname, lastname) {
> this.firstname = firstname;
> this.lastname  = lastname;
> },
> lazy fullname: this.firstname + " " + this.lastname
> });
>
> const john = new Person("John", "Doe");
> const jane = new Person("Jane", "Doe");
>
> console.log(john.fullname); // John Doe
> console.log(jane.fullname); // Jane Doe
>
> Note that the this within the lazy property value expression (i.e. within
> the expression this.firstname + " " + this.lastname) refers to the
> instance (i.e. either john or jane). This can be confusing because
> without the lazy keyword, this would refer to the lexical context.
> Although I'm comfortable with it yet I'm open to other suggestions.
>
>
> On Tue, Jun 12, 2018, at 3:31 AM, Jordan Harband wrote:
>
> How would this work when the getter lives on a prototype? (like most
> builtin getters) Would it install the memoized value on `this`, or on the
> object that contains the getter? Would it use [[Set]] or [[Define]]?
>
> On Tue, Jun 12, 2018 at 12:13 AM, Aadit M Shah 
> wrote:
>
>
> Hello TC39,
>
> I recently opened an issue  in
> the tc39/ecma262  repository, proposing
> a new syntax for lazy getters, and I was directed to the CONTRIBUTING
>  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
> .
> 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 === 0 ? 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 === 0 ? 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
>
>
>
> ___
> 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: [Proposal] New syntax for lazy getters

2018-06-12 Thread Aadit M Shah
When the getter lives on a prototype it would install the memoized value
on this using [[Define]]. This is the same way it would work in regular
lazy getters:
const defclass = prototype => {
const constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
};

const Person = defclass({
constructor: function Person(firstname, lastname) {
this.firstname = firstname;
this.lastname  = lastname;
},
lazy fullname: this.firstname + " " + this.lastname
});

const john = new Person("John", "Doe");
const jane = new Person("Jane", "Doe");

console.log(john.fullname); // John Doe
console.log(jane.fullname); // Jane Doe

Note that the this within the lazy property value expression (i.e.
within the expression this.firstname + " " + this.lastname) refers to
the instance (i.e. either john or jane). This can be confusing because
without the lazy keyword, this would refer to the lexical context.
Although I'm comfortable with it yet I'm open to other suggestions.

On Tue, Jun 12, 2018, at 3:31 AM, Jordan Harband wrote:
> How would this work when the getter lives on a prototype? (like most
> builtin getters) Would it install the memoized value on `this`, or on
> the object that contains the getter? Would it use [[Set]] or
> [[Define]]?> 
> On Tue, Jun 12, 2018 at 12:13 AM, Aadit M Shah
>  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
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Andrea Giammarchi
in case the counter proposal is not clear enough (apologies for that), this
should read simpler than that

```js
const take = (n, xs) => n === 0 ? null : xs && {
head: xs.head,
lazy tail() {
  const value = take(n - 1, xs.tail);
  Object.defineProperty(this, 'tail', {
configurable: false,
get: () => value
  });
  return value;
}
};
```

Hope it's clear what I'd change.

Best Regards

On Tue, Jun 12, 2018 at 9:45 AM, Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> * having an extra keyword ...
>
> On Tue, Jun 12, 2018 at 9:44 AM, Andrea Giammarchi <
> andrea.giammar...@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.
>>
>> *## 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,
>> 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 
>> wrote:
>>
>>> Hello TC39,
>>>
>>> I recently opened an issue  in
>>> the tc39/ecma262  repository,
>>> proposing a new syntax for lazy getters, and I was directed to the
>>> CONTRIBUTING
>>>  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
>>> .
>>> 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 === 0 ? 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 === 0 ? 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
>>>
>>>
>>
>
___
es-discuss mailing list
es-discuss@mozilla.org

Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Andrea Giammarchi
* having an extra keyword ...

On Tue, Jun 12, 2018 at 9:44 AM, Andrea Giammarchi <
andrea.giammar...@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.
>
> *## 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,
> 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 
> wrote:
>
>> Hello TC39,
>>
>> I recently opened an issue  in
>> the tc39/ecma262  repository, proposing
>> a new syntax for lazy getters, and I was directed to the CONTRIBUTING
>>  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
>> .
>> 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 === 0 ? 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 === 0 ? 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
>>
>>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Andrea Giammarchi
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 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,
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 
wrote:

> Hello TC39,
>
> I recently opened an issue  in
> the tc39/ecma262  repository, proposing
> a new syntax for lazy getters, and I was directed to the CONTRIBUTING
>  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
> .
> 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 === 0 ? 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 === 0 ? 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
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] New syntax for lazy getters

2018-06-12 Thread Jordan Harband
How would this work when the getter lives on a prototype? (like most
builtin getters) Would it install the memoized value on `this`, or on the
object that contains the getter? Would it use [[Set]] or [[Define]]?

On Tue, Jun 12, 2018 at 12:13 AM, Aadit M Shah 
wrote:

> Hello TC39,
>
> I recently opened an issue  in
> the tc39/ecma262  repository, proposing
> a new syntax for lazy getters, and I was directed to the CONTRIBUTING
>  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
> .
> 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 === 0 ? 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 === 0 ? 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
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss