Lazy evaluation

classic Classic list List threaded Threaded
54 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Lazy evaluation

Isiah Meadows-2
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
[hidden email]

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Andrea Giammarchi-2
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 <[hidden email]> 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
[hidden email]

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Naveen Chawla
Could you not do this with a promise? If not, what's missing in promise that you could do with "lazy"? Sorry if I've missed the whole premise

On Thu, 31 Aug 2017 at 19:09 Andrea Giammarchi <[hidden email]> 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 <[hidden email]> 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
[hidden email]

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Fwd: Lazy evaluation

Michael DeByl
In reply to this post by Andrea Giammarchi-2

I was going to read this in detail but I was too lazy to properly evaluate it



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Isiah Meadows-2
In reply to this post by Andrea Giammarchi-2
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
[hidden email]

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
<[hidden email]> 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 <[hidden email]>
> 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
>> [hidden email]
>>
>> Looking for web consulting? Or a new website?
>> Send me an email and we can get started.
>> www.isiahmeadows.com
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Andrea Giammarchi-2
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 <[hidden email]> 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
[hidden email]

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
<[hidden email]> 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 <[hidden email]>
> 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
>> [hidden email]
>>
>> Looking for web consulting? Or a new website?
>> Send me an email and we can get started.
>> www.isiahmeadows.com
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>
>


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Isiah Meadows-2
In reply to this post by Naveen Chawla
Promises are inherently eager, but also async - consider that `new
Promise(resolve => resolve(1))` is roughly equivalent to `var promise
= Promise.resolve(1)`.

My proposal is for a single immediate value, but created on demand
(when you call `.get()`) rather than immediately.
-----

Isiah Meadows
[hidden email]

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 10:37 AM, Naveen Chawla <[hidden email]> wrote:

> Could you not do this with a promise? If not, what's missing in promise that
> you could do with "lazy"? Sorry if I've missed the whole premise
>
> On Thu, 31 Aug 2017 at 19:09 Andrea Giammarchi <[hidden email]>
> 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 <[hidden email]>
>> 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
>>> [hidden email]
>>>
>>> Looking for web consulting? Or a new website?
>>> Send me an email and we can get started.
>>> www.isiahmeadows.com
>>> _______________________________________________
>>> es-discuss mailing list
>>> [hidden email]
>>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Isiah Meadows-2
In reply to this post by Andrea Giammarchi-2
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
[hidden email]

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
<[hidden email]> 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 <[hidden email]>
> 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
>> [hidden email]
>>
>> 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
>> <[hidden email]> 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 <[hidden email]>
>> > 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
>> >> [hidden email]
>> >>
>> >> Looking for web consulting? Or a new website?
>> >> Send me an email and we can get started.
>> >> www.isiahmeadows.com
>> >> _______________________________________________
>> >> es-discuss mailing list
>> >> [hidden email]
>> >> https://mail.mozilla.org/listinfo/es-discuss
>> >
>> >
>
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Andrea Giammarchi-2
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 <[hidden email]> 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
[hidden email]

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
<[hidden email]> 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 <[hidden email]>
> 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
>> [hidden email]
>>
>> 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
>> <[hidden email]> 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 <[hidden email]>
>> > 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
>> >> [hidden email]
>> >>
>> >> Looking for web consulting? Or a new website?
>> >> Send me an email and we can get started.
>> >> www.isiahmeadows.com
>> >> _______________________________________________
>> >> es-discuss mailing list
>> >> [hidden email]
>> >> https://mail.mozilla.org/listinfo/es-discuss
>> >
>> >
>
>


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Isiah Meadows-2
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
[hidden email]

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
<[hidden email]> 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 <[hidden email]>
> 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
>> [hidden email]
>>
>> 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
>> <[hidden email]> 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 <[hidden email]>
>> > 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
>> >> [hidden email]
>> >>
>> >> 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
>> >> <[hidden email]> 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
>> >> > <[hidden email]>
>> >> > 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
>> >> >> [hidden email]
>> >> >>
>> >> >> Looking for web consulting? Or a new website?
>> >> >> Send me an email and we can get started.
>> >> >> www.isiahmeadows.com
>> >> >> _______________________________________________
>> >> >> es-discuss mailing list
>> >> >> [hidden email]
>> >> >> https://mail.mozilla.org/listinfo/es-discuss
>> >> >
>> >> >
>> >
>> >
>
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Andrea Giammarchi-2
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




On Thu, Aug 31, 2017 at 6:03 PM, Isiah Meadows <[hidden email]> 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
[hidden email]

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
<[hidden email]> 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 <[hidden email]>
> 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
>> [hidden email]
>>
>> 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
>> <[hidden email]> 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 <[hidden email]>
>> > 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
>> >> [hidden email]
>> >>
>> >> 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
>> >> <[hidden email]> 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
>> >> > <[hidden email]>
>> >> > 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
>> >> >> [hidden email]
>> >> >>
>> >> >> Looking for web consulting? Or a new website?
>> >> >> Send me an email and we can get started.
>> >> >> www.isiahmeadows.com
>> >> >> _______________________________________________
>> >> >> es-discuss mailing list
>> >> >> [hidden email]
>> >> >> https://mail.mozilla.org/listinfo/es-discuss
>> >> >
>> >> >
>> >
>> >
>
>


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Andrea Giammarchi-2
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 <[hidden email]> 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




On Thu, Aug 31, 2017 at 6:03 PM, Isiah Meadows <[hidden email]> 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
[hidden email]

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
<[hidden email]> 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 <[hidden email]>
> 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
>> [hidden email]
>>
>> 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
>> <[hidden email]> 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 <[hidden email]>
>> > 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
>> >> [hidden email]
>> >>
>> >> 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
>> >> <[hidden email]> 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
>> >> > <[hidden email]>
>> >> > 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
>> >> >> [hidden email]
>> >> >>
>> >> >> Looking for web consulting? Or a new website?
>> >> >> Send me an email and we can get started.
>> >> >> www.isiahmeadows.com
>> >> >> _______________________________________________
>> >> >> es-discuss mailing list
>> >> >> [hidden email]
>> >> >> https://mail.mozilla.org/listinfo/es-discuss
>> >> >
>> >> >
>> >
>> >
>
>



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Isiah Meadows-2
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
[hidden email]

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
<[hidden email]> 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
> <[hidden email]> 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 <[hidden email]>
>> 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
>>> [hidden email]
>>>
>>> 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
>>> <[hidden email]> 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 <[hidden email]>
>>> > 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
>>> >> [hidden email]
>>> >>
>>> >> 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
>>> >> <[hidden email]> 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
>>> >> > <[hidden email]>
>>> >> > 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
>>> >> >> [hidden email]
>>> >> >>
>>> >> >> 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
>>> >> >> <[hidden email]> 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
>>> >> >> > <[hidden email]>
>>> >> >> > 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
>>> >> >> >> [hidden email]
>>> >> >> >>
>>> >> >> >> Looking for web consulting? Or a new website?
>>> >> >> >> Send me an email and we can get started.
>>> >> >> >> www.isiahmeadows.com
>>> >> >> >> _______________________________________________
>>> >> >> >> es-discuss mailing list
>>> >> >> >> [hidden email]
>>> >> >> >> https://mail.mozilla.org/listinfo/es-discuss
>>> >> >> >
>>> >> >> >
>>> >> >
>>> >> >
>>> >
>>> >
>>
>>
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Andrea Giammarchi-2
it wouldn't work, would it ? I mean, you still have to pass through the "ugly" _db.get() thingy, right?

how do you access and trigger the lazy bit within the class?

On Thu, Aug 31, 2017 at 7:56 PM, Isiah Meadows <[hidden email]> wrote:
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
[hidden email]

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
<[hidden email]> 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
> <[hidden email]> 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 <[hidden email]>
>> 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
>>> [hidden email]
>>>
>>> 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
>>> <[hidden email]> 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 <[hidden email]>
>>> > 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
>>> >> [hidden email]
>>> >>
>>> >> 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
>>> >> <[hidden email]> 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
>>> >> > <[hidden email]>
>>> >> > 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
>>> >> >> [hidden email]
>>> >> >>
>>> >> >> 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
>>> >> >> <[hidden email]> 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
>>> >> >> > <[hidden email]>
>>> >> >> > 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
>>> >> >> >> [hidden email]
>>> >> >> >>
>>> >> >> >> Looking for web consulting? Or a new website?
>>> >> >> >> Send me an email and we can get started.
>>> >> >> >> www.isiahmeadows.com
>>> >> >> >> _______________________________________________
>>> >> >> >> es-discuss mailing list
>>> >> >> >> [hidden email]
>>> >> >> >> https://mail.mozilla.org/listinfo/es-discuss
>>> >> >> >
>>> >> >> >
>>> >> >
>>> >> >
>>> >
>>> >
>>
>>
>


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Isiah Meadows-2
Note the TS-ish declaration above it. That's the variant I was
referring to (I presented about 3 different variants initially).

```ts
// The declaration I included
declare function lazy<T>(init: () => T): () => T;
```


On Thu, Aug 31, 2017 at 3:05 PM, Andrea Giammarchi
<[hidden email]> wrote:

> it wouldn't work, would it ? I mean, you still have to pass through the
> "ugly" _db.get() thingy, right?
>
> how do you access and trigger the lazy bit within the class?
>
> On Thu, Aug 31, 2017 at 7:56 PM, Isiah Meadows <[hidden email]>
> wrote:
>>
>> 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
>> [hidden email]
>>
>> 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
>> <[hidden email]> 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
>> > <[hidden email]> 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 <[hidden email]>
>> >> 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
>> >>> [hidden email]
>> >>>
>> >>> 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
>> >>> <[hidden email]> 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
>> >>> > <[hidden email]>
>> >>> > 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
>> >>> >> [hidden email]
>> >>> >>
>> >>> >> 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
>> >>> >> <[hidden email]> 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
>> >>> >> > <[hidden email]>
>> >>> >> > 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
>> >>> >> >> [hidden email]
>> >>> >> >>
>> >>> >> >> 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
>> >>> >> >> <[hidden email]> 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
>> >>> >> >> > <[hidden email]>
>> >>> >> >> > 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
>> >>> >> >> >> [hidden email]
>> >>> >> >> >>
>> >>> >> >> >> Looking for web consulting? Or a new website?
>> >>> >> >> >> Send me an email and we can get started.
>> >>> >> >> >> www.isiahmeadows.com
>> >>> >> >> >> _______________________________________________
>> >>> >> >> >> es-discuss mailing list
>> >>> >> >> >> [hidden email]
>> >>> >> >> >> https://mail.mozilla.org/listinfo/es-discuss
>> >>> >> >> >
>> >>> >> >> >
>> >>> >> >
>> >>> >> >
>> >>> >
>> >>> >
>> >>
>> >>
>> >
>
>

-----

Isiah Meadows
[hidden email]

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Andrea Giammarchi-2
Sorry I don't speak TS, I speak ES.

Can you please tell me in JavaScript what does that do?

On Thu, Aug 31, 2017 at 8:18 PM, Isiah Meadows <[hidden email]> wrote:
Note the TS-ish declaration above it. That's the variant I was
referring to (I presented about 3 different variants initially).

```ts
// The declaration I included
declare function lazy<T>(init: () => T): () => T;
```


On Thu, Aug 31, 2017 at 3:05 PM, Andrea Giammarchi
<[hidden email]> wrote:
> it wouldn't work, would it ? I mean, you still have to pass through the
> "ugly" _db.get() thingy, right?
>
> how do you access and trigger the lazy bit within the class?
>
> On Thu, Aug 31, 2017 at 7:56 PM, Isiah Meadows <[hidden email]>
> wrote:
>>
>> 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
>> [hidden email]
>>
>> 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
>> <[hidden email]> 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
>> > <[hidden email]> 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 <[hidden email]>
>> >> 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
>> >>> [hidden email]
>> >>>
>> >>> 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
>> >>> <[hidden email]> 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
>> >>> > <[hidden email]>
>> >>> > 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
>> >>> >> [hidden email]
>> >>> >>
>> >>> >> 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
>> >>> >> <[hidden email]> 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
>> >>> >> > <[hidden email]>
>> >>> >> > 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
>> >>> >> >> [hidden email]
>> >>> >> >>
>> >>> >> >> 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
>> >>> >> >> <[hidden email]> 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
>> >>> >> >> > <[hidden email]>
>> >>> >> >> > 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
>> >>> >> >> >> [hidden email]
>> >>> >> >> >>
>> >>> >> >> >> Looking for web consulting? Or a new website?
>> >>> >> >> >> Send me an email and we can get started.
>> >>> >> >> >> www.isiahmeadows.com
>> >>> >> >> >> _______________________________________________
>> >>> >> >> >> es-discuss mailing list
>> >>> >> >> >> [hidden email]
>> >>> >> >> >> https://mail.mozilla.org/listinfo/es-discuss
>> >>> >> >> >
>> >>> >> >> >
>> >>> >> >
>> >>> >> >
>> >>> >
>> >>> >
>> >>
>> >>
>> >
>
>

-----

Isiah Meadows
[hidden email]

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


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Isiah Meadows-2
It takes a function, and returns a function that (if necessary)
initializes the value and then gets it.
-----

Isiah Meadows
[hidden email]

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 3:43 PM, Andrea Giammarchi
<[hidden email]> wrote:

> Sorry I don't speak TS, I speak ES.
>
> Can you please tell me in JavaScript what does that do?
>
> On Thu, Aug 31, 2017 at 8:18 PM, Isiah Meadows <[hidden email]>
> wrote:
>>
>> Note the TS-ish declaration above it. That's the variant I was
>> referring to (I presented about 3 different variants initially).
>>
>> ```ts
>> // The declaration I included
>> declare function lazy<T>(init: () => T): () => T;
>> ```
>>
>>
>> On Thu, Aug 31, 2017 at 3:05 PM, Andrea Giammarchi
>> <[hidden email]> wrote:
>> > it wouldn't work, would it ? I mean, you still have to pass through the
>> > "ugly" _db.get() thingy, right?
>> >
>> > how do you access and trigger the lazy bit within the class?
>> >
>> > On Thu, Aug 31, 2017 at 7:56 PM, Isiah Meadows <[hidden email]>
>> > wrote:
>> >>
>> >> 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
>> >> [hidden email]
>> >>
>> >> 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
>> >> <[hidden email]> 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
>> >> > <[hidden email]> 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
>> >> >> <[hidden email]>
>> >> >> 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
>> >> >>> [hidden email]
>> >> >>>
>> >> >>> 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
>> >> >>> <[hidden email]> 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
>> >> >>> > <[hidden email]>
>> >> >>> > 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
>> >> >>> >> [hidden email]
>> >> >>> >>
>> >> >>> >> 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
>> >> >>> >> <[hidden email]> 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
>> >> >>> >> > <[hidden email]>
>> >> >>> >> > 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
>> >> >>> >> >> [hidden email]
>> >> >>> >> >>
>> >> >>> >> >> 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
>> >> >>> >> >> <[hidden email]> 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
>> >> >>> >> >> > <[hidden email]>
>> >> >>> >> >> > 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
>> >> >>> >> >> >> [hidden email]
>> >> >>> >> >> >>
>> >> >>> >> >> >> Looking for web consulting? Or a new website?
>> >> >>> >> >> >> Send me an email and we can get started.
>> >> >>> >> >> >> www.isiahmeadows.com
>> >> >>> >> >> >> _______________________________________________
>> >> >>> >> >> >> es-discuss mailing list
>> >> >>> >> >> >> [hidden email]
>> >> >>> >> >> >> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>> >> >> >
>> >> >>> >> >> >
>> >> >>> >> >
>> >> >>> >> >
>> >> >>> >
>> >> >>> >
>> >> >>
>> >> >>
>> >> >
>> >
>> >
>>
>> -----
>>
>> Isiah Meadows
>> [hidden email]
>>
>> Looking for web consulting? Or a new website?
>> Send me an email and we can get started.
>> www.isiahmeadows.com
>
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Andrea Giammarchi-2
so in JavaScript that results into this._db() each time, resolved lazily with the first value returned once ?

I still think my approach is cleaner and more transparent.

`get _thing() { return defineProperty(this, 'thing', value) }`

but if your TS-ish stuff translates into that, works for me



On Thu, Aug 31, 2017 at 8:49 PM, Isiah Meadows <[hidden email]> wrote:
It takes a function, and returns a function that (if necessary)
initializes the value and then gets it.
-----

Isiah Meadows
[hidden email]

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 3:43 PM, Andrea Giammarchi
<[hidden email]> wrote:
> Sorry I don't speak TS, I speak ES.
>
> Can you please tell me in JavaScript what does that do?
>
> On Thu, Aug 31, 2017 at 8:18 PM, Isiah Meadows <[hidden email]>
> wrote:
>>
>> Note the TS-ish declaration above it. That's the variant I was
>> referring to (I presented about 3 different variants initially).
>>
>> ```ts
>> // The declaration I included
>> declare function lazy<T>(init: () => T): () => T;
>> ```
>>
>>
>> On Thu, Aug 31, 2017 at 3:05 PM, Andrea Giammarchi
>> <[hidden email]> wrote:
>> > it wouldn't work, would it ? I mean, you still have to pass through the
>> > "ugly" _db.get() thingy, right?
>> >
>> > how do you access and trigger the lazy bit within the class?
>> >
>> > On Thu, Aug 31, 2017 at 7:56 PM, Isiah Meadows <[hidden email]>
>> > wrote:
>> >>
>> >> 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
>> >> [hidden email]
>> >>
>> >> 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
>> >> <[hidden email]> 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
>> >> > <[hidden email]> 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
>> >> >> <[hidden email]>
>> >> >> 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
>> >> >>> [hidden email]
>> >> >>>
>> >> >>> 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
>> >> >>> <[hidden email]> 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
>> >> >>> > <[hidden email]>
>> >> >>> > 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
>> >> >>> >> [hidden email]
>> >> >>> >>
>> >> >>> >> 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
>> >> >>> >> <[hidden email]> 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
>> >> >>> >> > <[hidden email]>
>> >> >>> >> > 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
>> >> >>> >> >> [hidden email]
>> >> >>> >> >>
>> >> >>> >> >> 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
>> >> >>> >> >> <[hidden email]> 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
>> >> >>> >> >> > <[hidden email]>
>> >> >>> >> >> > 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
>> >> >>> >> >> >> [hidden email]
>> >> >>> >> >> >>
>> >> >>> >> >> >> Looking for web consulting? Or a new website?
>> >> >>> >> >> >> Send me an email and we can get started.
>> >> >>> >> >> >> www.isiahmeadows.com
>> >> >>> >> >> >> _______________________________________________
>> >> >>> >> >> >> es-discuss mailing list
>> >> >>> >> >> >> [hidden email]
>> >> >>> >> >> >> https://mail.mozilla.org/listinfo/es-discuss
>> >> >>> >> >> >
>> >> >>> >> >> >
>> >> >>> >> >
>> >> >>> >> >
>> >> >>> >
>> >> >>> >
>> >> >>
>> >> >>
>> >> >
>> >
>> >
>>
>> -----
>>
>> Isiah Meadows
>> [hidden email]
>>
>> Looking for web consulting? Or a new website?
>> Send me an email and we can get started.
>> www.isiahmeadows.com
>
>


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Isiah Meadows-2
Yes. I'll point out that having it as a function, rather than a
property-specific thing, makes it more flexible, since you can define
constants as lazy values (I do that in quite a few places).

If you want to make it transparent, it's not that hard to make a
single-line getter/method that hides the abstraction.

Granted, most of my lazy values are properties, not constants, so I
could consider it an acceptable compromise.
-----

Isiah Meadows
[hidden email]

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 3:54 PM, Andrea Giammarchi
<[hidden email]> wrote:

> so in JavaScript that results into this._db() each time, resolved lazily
> with the first value returned once ?
>
> I still think my approach is cleaner and more transparent.
>
> `get _thing() { return defineProperty(this, 'thing', value) }`
>
> but if your TS-ish stuff translates into that, works for me
>
>
>
> On Thu, Aug 31, 2017 at 8:49 PM, Isiah Meadows <[hidden email]>
> wrote:
>>
>> It takes a function, and returns a function that (if necessary)
>> initializes the value and then gets it.
>> -----
>>
>> Isiah Meadows
>> [hidden email]
>>
>> 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 3:43 PM, Andrea Giammarchi
>> <[hidden email]> wrote:
>> > Sorry I don't speak TS, I speak ES.
>> >
>> > Can you please tell me in JavaScript what does that do?
>> >
>> > On Thu, Aug 31, 2017 at 8:18 PM, Isiah Meadows <[hidden email]>
>> > wrote:
>> >>
>> >> Note the TS-ish declaration above it. That's the variant I was
>> >> referring to (I presented about 3 different variants initially).
>> >>
>> >> ```ts
>> >> // The declaration I included
>> >> declare function lazy<T>(init: () => T): () => T;
>> >> ```
>> >>
>> >>
>> >> On Thu, Aug 31, 2017 at 3:05 PM, Andrea Giammarchi
>> >> <[hidden email]> wrote:
>> >> > it wouldn't work, would it ? I mean, you still have to pass through
>> >> > the
>> >> > "ugly" _db.get() thingy, right?
>> >> >
>> >> > how do you access and trigger the lazy bit within the class?
>> >> >
>> >> > On Thu, Aug 31, 2017 at 7:56 PM, Isiah Meadows
>> >> > <[hidden email]>
>> >> > wrote:
>> >> >>
>> >> >> 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
>> >> >> [hidden email]
>> >> >>
>> >> >> 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
>> >> >> <[hidden email]> 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
>> >> >> > <[hidden email]> 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
>> >> >> >> <[hidden email]>
>> >> >> >> 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
>> >> >> >>> [hidden email]
>> >> >> >>>
>> >> >> >>> 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
>> >> >> >>> <[hidden email]> 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
>> >> >> >>> > <[hidden email]>
>> >> >> >>> > 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
>> >> >> >>> >> [hidden email]
>> >> >> >>> >>
>> >> >> >>> >> 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
>> >> >> >>> >> <[hidden email]> 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
>> >> >> >>> >> > <[hidden email]>
>> >> >> >>> >> > 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
>> >> >> >>> >> >> [hidden email]
>> >> >> >>> >> >>
>> >> >> >>> >> >> 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
>> >> >> >>> >> >> <[hidden email]> 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
>> >> >> >>> >> >> > <[hidden email]>
>> >> >> >>> >> >> > 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
>> >> >> >>> >> >> >> [hidden email]
>> >> >> >>> >> >> >>
>> >> >> >>> >> >> >> Looking for web consulting? Or a new website?
>> >> >> >>> >> >> >> Send me an email and we can get started.
>> >> >> >>> >> >> >> www.isiahmeadows.com
>> >> >> >>> >> >> >> _______________________________________________
>> >> >> >>> >> >> >> es-discuss mailing list
>> >> >> >>> >> >> >> [hidden email]
>> >> >> >>> >> >> >> https://mail.mozilla.org/listinfo/es-discuss
>> >> >> >>> >> >> >
>> >> >> >>> >> >> >
>> >> >> >>> >> >
>> >> >> >>> >> >
>> >> >> >>> >
>> >> >> >>> >
>> >> >> >>
>> >> >> >>
>> >> >> >
>> >> >
>> >> >
>> >>
>> >> -----
>> >>
>> >> Isiah Meadows
>> >> [hidden email]
>> >>
>> >> Looking for web consulting? Or a new website?
>> >> Send me an email and we can get started.
>> >> www.isiahmeadows.com
>> >
>> >
>
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Lazy evaluation

Andrea Giammarchi-2
it's a matter of semantics.

If I see this

```js
var later = anyWrappingName(() => Math.random());

// this is an assumption, not something obvious
later() === later()
```

If instead, I write this:
```js
this.later === this.later;
```

I expect that to never possibly fail like `arr.length === arr.length` or any `obj.prop`, in APIs with common sense, are equal to `obj.prop`.

Invokes via instances and objects? It's never obvious at first look, if that is a method execution, but it's surely a new invoke.

If you've trapped once the result behind the scene, reading that, is just noise for anyone eyes.

So, once again, are we proposing something that results into exactly this?

```js
class Later {
  get thing() {
    return Object.defineProperty(this, 'thing', {value: anyLazy()});
  }
  constructor() {
    // always true, no matter when/where
    this.thing === this.thing;
  }
}
```

If so, I'm happy. If not, this is confusing and solving not much.


Best Regards


On Thu, Aug 31, 2017 at 9:14 PM, Isiah Meadows <[hidden email]> wrote:
Yes. I'll point out that having it as a function, rather than a
property-specific thing, makes it more flexible, since you can define
constants as lazy values (I do that in quite a few places).

If you want to make it transparent, it's not that hard to make a
single-line getter/method that hides the abstraction.

Granted, most of my lazy values are properties, not constants, so I
could consider it an acceptable compromise.
-----

Isiah Meadows
[hidden email]

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 3:54 PM, Andrea Giammarchi
<[hidden email]> wrote:
> so in JavaScript that results into this._db() each time, resolved lazily
> with the first value returned once ?
>
> I still think my approach is cleaner and more transparent.
>
> `get _thing() { return defineProperty(this, 'thing', value) }`
>
> but if your TS-ish stuff translates into that, works for me
>
>
>
> On Thu, Aug 31, 2017 at 8:49 PM, Isiah Meadows <[hidden email]>
> wrote:
>>
>> It takes a function, and returns a function that (if necessary)
>> initializes the value and then gets it.
>> -----
>>
>> Isiah Meadows
>> [hidden email]
>>
>> 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 3:43 PM, Andrea Giammarchi
>> <[hidden email]> wrote:
>> > Sorry I don't speak TS, I speak ES.
>> >
>> > Can you please tell me in JavaScript what does that do?
>> >
>> > On Thu, Aug 31, 2017 at 8:18 PM, Isiah Meadows <[hidden email]>
>> > wrote:
>> >>
>> >> Note the TS-ish declaration above it. That's the variant I was
>> >> referring to (I presented about 3 different variants initially).
>> >>
>> >> ```ts
>> >> // The declaration I included
>> >> declare function lazy<T>(init: () => T): () => T;
>> >> ```
>> >>
>> >>
>> >> On Thu, Aug 31, 2017 at 3:05 PM, Andrea Giammarchi
>> >> <[hidden email]> wrote:
>> >> > it wouldn't work, would it ? I mean, you still have to pass through
>> >> > the
>> >> > "ugly" _db.get() thingy, right?
>> >> >
>> >> > how do you access and trigger the lazy bit within the class?
>> >> >
>> >> > On Thu, Aug 31, 2017 at 7:56 PM, Isiah Meadows
>> >> > <[hidden email]>
>> >> > wrote:
>> >> >>
>> >> >> 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
>> >> >> [hidden email]
>> >> >>
>> >> >> 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
>> >> >> <[hidden email]> 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
>> >> >> > <[hidden email]> 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
>> >> >> >> <[hidden email]>
>> >> >> >> 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
>> >> >> >>> [hidden email]
>> >> >> >>>
>> >> >> >>> 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
>> >> >> >>> <[hidden email]> 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
>> >> >> >>> > <[hidden email]>
>> >> >> >>> > 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
>> >> >> >>> >> [hidden email]
>> >> >> >>> >>
>> >> >> >>> >> 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
>> >> >> >>> >> <[hidden email]> 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
>> >> >> >>> >> > <[hidden email]>
>> >> >> >>> >> > 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
>> >> >> >>> >> >> [hidden email]
>> >> >> >>> >> >>
>> >> >> >>> >> >> 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
>> >> >> >>> >> >> <[hidden email]> 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
>> >> >> >>> >> >> > <[hidden email]>
>> >> >> >>> >> >> > 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
>> >> >> >>> >> >> >> [hidden email]
>> >> >> >>> >> >> >>
>> >> >> >>> >> >> >> Looking for web consulting? Or a new website?
>> >> >> >>> >> >> >> Send me an email and we can get started.
>> >> >> >>> >> >> >> www.isiahmeadows.com
>> >> >> >>> >> >> >> _______________________________________________
>> >> >> >>> >> >> >> es-discuss mailing list
>> >> >> >>> >> >> >> [hidden email]
>> >> >> >>> >> >> >> https://mail.mozilla.org/listinfo/es-discuss
>> >> >> >>> >> >> >
>> >> >> >>> >> >> >
>> >> >> >>> >> >
>> >> >> >>> >> >
>> >> >> >>> >
>> >> >> >>> >
>> >> >> >>
>> >> >> >>
>> >> >> >
>> >> >
>> >> >
>> >>
>> >> -----
>> >>
>> >> Isiah Meadows
>> >> [hidden email]
>> >>
>> >> Looking for web consulting? Or a new website?
>> >> Send me an email and we can get started.
>> >> www.isiahmeadows.com
>> >
>> >
>
>


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
123