What about this (using the stage 3 class fields proposal)?

```js
declare function lazy<T>(init: () => T): () => T;

class WithLazyVals {
    _db = lazy(() => new Promise(...));
}
```
-----

Isiah Meadows
m...@isiahmeadows.com

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com


On Thu, Aug 31, 2017 at 1:34 PM, Andrea Giammarchi
<andrea.giammar...@gmail.com> wrote:
>> this proposal doesn't compose well with classes
>
> to expand a little, if you were proposing
>
> ```js
> class WithLazyVals {
>   lazy _db() { return new Promise(...); }
> }
> ```
>
> I would've taken first flight to come over and hug you.
>
> Best Regards
>
>
>
>
> On Thu, Aug 31, 2017 at 6:25 PM, Andrea Giammarchi
> <andrea.giammar...@gmail.com> wrote:
>>
>> > How often do you start out with a class like this ...
>>
>> Never, like I've said. This is the lazy pattern I know since ever.
>>
>> ```js
>> class Foo {
>>   get _db() {
>>     return Object.defineProperty(this, '_db', {
>>       value: new Promise((resolve, reject) => {
>>         // open a database connection
>>         // set up whatever tables you need to
>>         // etc.
>>       })
>>     })._db;
>>   }
>> }
>> ```
>>
>> Whenever you need, you just access `this._db`, no need to create an
>> enumerable variable and a class method.
>>
>> It looks cleaner to me.
>>
>>
>> > Things you don't want to initialize right away because initialization
>>
>> You don't really have to convince me, I've written lazy properties since
>> getters and setters were introduced [1]
>>
>> All I am saying is that this proposal doesn't compose well with classes,
>> it's just yet another SuperPrimitive for the language.
>>
>> It is also something trivial to implement on user land, yet I haven't seen
>> many writing code like the following:
>>
>> ```js
>> function Lazy(fn) {
>>   let c = false, v;
>>   return {get(){ return c ? v : (c = !c, v = fn()) }};
>> }
>>
>> var o = Lazy(() => Math.random());
>> o.get(); // ...
>> ```
>>
>> Maybe it's me that hasn't seen this widely adopted from some library?
>>
>> Anyway, this is just my opinion, maybe others would be happy with this.
>>
>> Best Regards
>>
>> [1] Class.lazy example
>> https://github.com/WebReflection/prototypal/blob/master/Class.md#classlazycallback
>>
>>
>>
>> On Thu, Aug 31, 2017 at 6:03 PM, Isiah Meadows <isiahmead...@gmail.com>
>> wrote:
>>>
>>> It'd solve a problem similarly to Kotlin's `by lazy { ... }` delegate,
>>> .NET's `System.Lazy<T>`, Swift's `lazy var`, among many other
>>> languages. It's very useful for lazy initialization [1], such as
>>> lazily setting up a database, requesting a resource, among other
>>> costly things. [2]
>>>
>>> How often do you start out with a class like this, where you have an
>>> expensive resource you don't want to open right away?
>>>
>>> ```js
>>> class Foo {
>>>     constructor() {
>>>         this._db = undefined
>>>     }
>>>
>>>     _initDb() {
>>>         if (this._db) return this._db
>>>         return this._db = new Promise((resolve, reject) => {
>>>             // open a database connection
>>>             // set up whatever tables you need to
>>>             // etc.
>>>         })
>>>     }
>>> }
>>> ```
>>>
>>> Or maybe, a large lookup table that takes a while to build, and might
>>> not even be used, so you don't want to do it on load?
>>>
>>> ```js
>>> var table
>>>
>>> function initTable() {
>>>     if (table) return
>>>     table = new Array(10000)
>>>     // do some expensive calculations
>>> }
>>> ```
>>>
>>> Things you don't want to initialize right away because initialization
>>> is expensive and/or the value might not even be used. That's the
>>> problem I'm aiming to solve, and it's something I feel would be useful
>>> in its own right in the language, about equal in importance to weak
>>> references. (Slightly specialized, but the need is not non-zero.)
>>>
>>> [1]: https://en.wikipedia.org/wiki/Lazy_initialization
>>> [2]:
>>> https://stackoverflow.com/questions/978759/what-is-lazy-initialization-and-why-is-it-useful
>>> -----
>>>
>>> Isiah Meadows
>>> m...@isiahmeadows.com
>>>
>>> Looking for web consulting? Or a new website?
>>> Send me an email and we can get started.
>>> www.isiahmeadows.com
>>>
>>>
>>> On Thu, Aug 31, 2017 at 12:23 PM, Andrea Giammarchi
>>> <andrea.giammar...@gmail.com> wrote:
>>> > right ... so ... I'm not sure I understand what this proposal would
>>> > solve.
>>> >
>>> > Instead of this:
>>> > ```js
>>> > obj.val || (obj.val = getValue())
>>> > ```
>>> >
>>> > you want to do this
>>> > ```js
>>> > (obj.val || (obj.val = new Lazy(getValue)).get();
>>> > ```
>>> >
>>> > Where is the "win" and why is that?
>>> >
>>> >
>>> >
>>> > On Thu, Aug 31, 2017 at 5:18 PM, Isiah Meadows <isiahmead...@gmail.com>
>>> > wrote:
>>> >>
>>> >> With my proposed `Lazy` class, if you were to use an instance as a
>>> >> descriptor, the `this` value it'd receive would not be a `Lazy`
>>> >> instance like it'd expect.
>>> >>
>>> >> Consider it the difference between `a.self` and `b.get()` in your
>>> >> example. `b.get()` is what I'd be expecting.
>>> >> -----
>>> >>
>>> >> Isiah Meadows
>>> >> m...@isiahmeadows.com
>>> >>
>>> >> Looking for web consulting? Or a new website?
>>> >> Send me an email and we can get started.
>>> >> www.isiahmeadows.com
>>> >>
>>> >>
>>> >> On Thu, Aug 31, 2017 at 12:12 PM, Andrea Giammarchi
>>> >> <andrea.giammar...@gmail.com> wrote:
>>> >> >> using it in a descriptor would get it passed the wrong `this`
>>> >> >
>>> >> > sorry, what?
>>> >> >
>>> >> > ```js
>>> >> > var a = {};
>>> >> > var b = {get() { return this; }};
>>> >> > Object.defineProperty(a, 'self', b);
>>> >> >
>>> >> > a.self === a; // true
>>> >> > ```
>>> >> >
>>> >> >
>>> >> > On Thu, Aug 31, 2017 at 5:09 PM, Isiah Meadows
>>> >> > <isiahmead...@gmail.com>
>>> >> > wrote:
>>> >> >>
>>> >> >> No. `Lazy` is intended to be an object to be used directly, not a
>>> >> >> descriptor of any kind.
>>> >> >>
>>> >> >> (My `lazy.get()` is an unbound method, so using it in a descriptor
>>> >> >> would get it passed the wrong `this`.)
>>> >> >> -----
>>> >> >>
>>> >> >> Isiah Meadows
>>> >> >> m...@isiahmeadows.com
>>> >> >>
>>> >> >> Looking for web consulting? Or a new website?
>>> >> >> Send me an email and we can get started.
>>> >> >> www.isiahmeadows.com
>>> >> >>
>>> >> >>
>>> >> >> On Thu, Aug 31, 2017 at 9:39 AM, Andrea Giammarchi
>>> >> >> <andrea.giammar...@gmail.com> wrote:
>>> >> >> > the following is how I usually consider lazy values
>>> >> >> >
>>> >> >> > ```js
>>> >> >> > class Any {
>>> >> >> >   _lazy(name) {
>>> >> >> >     switch (name) {
>>> >> >> >       case 'uid': return Math.random();
>>> >> >> >       // others ... eventually
>>> >> >> >     }
>>> >> >> >   }
>>> >> >> >   get uid() {
>>> >> >> >     var value = this._lazy('uid');
>>> >> >> >     // from now on, direct access
>>> >> >> >     Object.defineProperty(this, 'uid', {value});
>>> >> >> >     return value;
>>> >> >> >   }
>>> >> >> > }
>>> >> >> >
>>> >> >> > const a = new Any;
>>> >> >> > a.uid === a.uid; // true
>>> >> >> > ```
>>> >> >> >
>>> >> >> > If I understand correctly your proposal is to use Lazy as generic
>>> >> >> > descriptor, is that correct ?
>>> >> >> >
>>> >> >> > ```js
>>> >> >> > Object.defineProperty({}, 'something', new Lazy(function (val) {
>>> >> >> >   return this.shakaLaka ? val : 'no shakaLaka';
>>> >> >> > }));
>>> >> >> > ```
>>> >> >> >
>>> >> >> > ???
>>> >> >> >
>>> >> >> > If that's the case I see already people confused by arrow
>>> >> >> > function
>>> >> >> > in case they need to access the context,
>>> >> >> > plus no property access optimization once resolved.
>>> >> >> >
>>> >> >> > It's also not clear if such property can be set again later on
>>> >> >> > (right
>>> >> >> > now it
>>> >> >> > cannot)
>>> >> >> > 'cause lazy definition doesn't always necessarily mean inability
>>> >> >> > to
>>> >> >> > reassign.
>>> >> >> >
>>> >> >> > What am I missing/misunderstanding?
>>> >> >> >
>>> >> >> > Regards
>>> >> >> >
>>> >> >> >
>>> >> >> >
>>> >> >> > On Thu, Aug 31, 2017 at 2:21 PM, Isiah Meadows
>>> >> >> > <isiahmead...@gmail.com>
>>> >> >> > wrote:
>>> >> >> >>
>>> >> >> >> It'd be really nice if lazy values made it into the spec
>>> >> >> >> somehow.
>>> >> >> >> I've
>>> >> >> >> already found myself using things like this [1] quite a bit, and
>>> >> >> >> I've
>>> >> >> >> also found myself frequently initializing properties not on
>>> >> >> >> first
>>> >> >> >> access.
>>> >> >> >>
>>> >> >> >> [1]:
>>> >> >> >>
>>> >> >> >>
>>> >> >> >> https://gist.github.com/isiahmeadows/4c0723bdfa555a1c2cb01341b323c3d4
>>> >> >> >>
>>> >> >> >> As for what would be a nice API, maybe something like one of
>>> >> >> >> these?
>>> >> >> >>
>>> >> >> >> ```js
>>> >> >> >> class Lazy<T> {
>>> >> >> >>     constructor(init: () => T);
>>> >> >> >>     get(): T; // or error thrown
>>> >> >> >> }
>>> >> >> >>
>>> >> >> >> function lazy<T>(init: () => T): () => T; // or error thrown
>>> >> >> >>
>>> >> >> >> function lazy<T>(init: () => T): {
>>> >> >> >>     get(): T; // or error thrown
>>> >> >> >> }
>>> >> >> >> ```
>>> >> >> >>
>>> >> >> >> Alternatively, syntax might work, with `do` expression
>>> >> >> >> semantics:
>>> >> >> >>
>>> >> >> >> ```js
>>> >> >> >> const x = lazy do { ... }
>>> >> >> >> // expose via `x.get()` or just `x()`
>>> >> >> >> ```
>>> >> >> >>
>>> >> >> >> -----
>>> >> >> >>
>>> >> >> >> Isiah Meadows
>>> >> >> >> m...@isiahmeadows.com
>>> >> >> >>
>>> >> >> >> Looking for web consulting? Or a new website?
>>> >> >> >> Send me an email and we can get started.
>>> >> >> >> www.isiahmeadows.com
>>> >> >> >> _______________________________________________
>>> >> >> >> es-discuss mailing list
>>> >> >> >> es-discuss@mozilla.org
>>> >> >> >> https://mail.mozilla.org/listinfo/es-discuss
>>> >> >> >
>>> >> >> >
>>> >> >
>>> >> >
>>> >
>>> >
>>
>>
>
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to