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