Lazy evaluation

Andrea Giammarchi andrea.giammarchi at gmail.com
Sat Sep 16 08:39:40 UTC 2017


there's nothing bad in using accessors (getters/setters) but you can do
what you want, just don't tell everyone what you do is the only way 'cause
it's not.

I'm off this thread, there's probably nothing else to add.

Best Regards

On Sat, Sep 16, 2017 at 9:15 AM, kai zhu <kaizhu256 at gmail.com> wrote:

> you can call it dogma.  i call it the the javascript-way of solving
> frontend-engineering problems, which is simpler and more practical for
> laymen than what i learned from cs-theory in school using c++/java.
>
> its time we showed some pride in javascript (like the haskell/lisp/etc
> folks), and admit some of our 20+ year-old “hacks” are actually good
> design-patterns that rival and challenge traditional cs-teachings, instead
> of replacing them with bad-practices from other languages (*cough*
> operator-overloading *cough*).
>
> On Sep 14, 2017, at 4:26 PM, Andrea Giammarchi <
> andrea.giammarchi at gmail.com> wrote:
>
> > please use normal method-calls instead, which are more maintainable
>
> no, thanks.
>
>
> > WeakMap's implicit-garbage-collecting feature is error-prone, hard to
> validate with tests, and generally becomes unmaintainable over time.
>
> no, thanks.
>
> We were discussing patterns here, nothing to "please don't" and IMO, dogma
> oriented rules are over-engineered anti-pattern too.
>
> Let's not make this ML an awkward place for who wants to just learn or
> explore JS language features, thanks.
>
>
>
>
>
> On Thu, Sep 14, 2017 at 9:55 AM, kai zhu <kaizhu256 at gmail.com> wrote:
>
>> inline
>>
>> ```js
>>> class A {
>>>   #random;
>>>   get random() {
>>>     return this.#random ||
>>>           (this.#random = Math.random());
>>>   }
>>> }
>>>
>>>
>>> // transpiled
>>> var A = function (wm) {
>>>   function A() {
>>>     wm.set(this, {random: void 0});
>>>   }
>>>   Object.defineProperties(
>>>     A.prototype,
>>>     {
>>>       random: {
>>>         configurable: true,
>>>         get: function () {
>>>           return wm.get(this).random ||
>>>                 (wm.get(this).random = Math.random());
>>>         }
>>>       }
>>>     }
>>>   );
>>>   return A;
>>> }(new WeakMap);
>>> ```
>>
>>
>> - overloaded getters/setters and Object.defineProperties are generally *over-engineered
>> *anti-patterns in javascript-programming
>> * please use normal method-calls instead, which are more maintainable
>>
>> - WeakMap is an *over-engineered *anti-pattern in javascript-programming
>> * they are inferior to using a plain-object cache-dictionary in pretty
>> much every use-case.
>> * WeakMap's implicit-garbage-collecting feature is error-prone, hard to
>> validate with tests, and generally becomes unmaintainable over time.
>>
>> ```javascript
>> /*jslint node: true */
>> 'use strict';
>>
>> function LazyClass() {
>>     this.cacheDict = {};
>> }
>> LazyClass.prototype.getRandomCached = function () {
>>     this.cacheDict.random = this.cacheDict.random || Math.random();
>>     return this.cacheDict.random;
>> };
>> LazyClass.prototype.clearCache = function () {
>>     this.cacheDict = {};
>> };
>>
>> var lazyObject = new LazyClass();
>> console.log(lazyObject.getRandomCached());
>> console.log(lazyObject.getRandomCached());
>> lazyObject.clearCache();
>> console.log(lazyObject.getRandomCached());
>> ```
>>
>> <PastedGraphic-4.png>
>>
>>
>>
>> On Sep 13, 2017, at 9:32 PM, Andrea Giammarchi <
>> andrea.giammarchi at gmail.com> wrote:
>>
>> > Maybe you mean "will behave more or less as if (except more
>> efficiently)"?
>>
>> no, I meant: it will transpiled into something using private WeakMaps.
>>
>> I don't have any interest in talk nanoseconds for something unrelated to
>> the topic though.
>>
>> Best Regards
>>
>> On Wed, Sep 13, 2017 at 1:54 PM, Alex Kodat <alexkodat at gmail.com> wrote:
>>
>>> What do you mean by “will be transpiled through”? My understanding of
>>> the private property proposal is that private properties will be in fixed
>>> slots (inaccessible outside the class) in the object so there would be no
>>> WeakMap. Maybe you mean "will behave more or less as if (except more
>>> efficiently)"?
>>>
>>> ----
>>> Alex Kodat
>>>
>>> From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of
>>> Andrea Giammarchi
>>> Sent: Wednesday, September 13, 2017 2:31 AM
>>> To: Steve Fink <sphink at gmail.com>
>>> Cc: es-discuss at mozilla.org
>>> Subject: Re: Lazy evaluation
>>>
>>> > The properties already existed, so defineProperty shouldn't modify the
>>> order IIUC
>>>
>>> well, nope. the property existed in the prototype, not in the object.
>>>
>>> anyway, I guess private properties, that are a possible solution, will
>>> be transpiled through a WeakMap so that most likely anything discussed in
>>> here won't make sense and the future code would look like the following
>>>
>>> ```js
>>> class A {
>>>   #random;
>>>   get random() {
>>>     return this.#random ||
>>>           (this.#random = Math.random());
>>>   }
>>> }
>>>
>>>
>>> // transpiled
>>> var A = function (wm) {
>>>   function A() {
>>>     wm.set(this, {random: void 0});
>>>   }
>>>   Object.defineProperties(
>>>     A.prototype,
>>>     {
>>>       random: {
>>>         configurable: true,
>>>         get: function () {
>>>           return wm.get(this).random ||
>>>                 (wm.get(this).random = Math.random());
>>>         }
>>>       }
>>>     }
>>>   );
>>>   return A;
>>> }(new WeakMap);
>>> ```
>>>
>>>
>>>
>>>
>>>
>>>
>>> On Tue, Sep 12, 2017 at 10:39 PM, Steve Fink <mailto:sphink at gmail.com>
>>> wrote:
>>> My intent was only to respond to the performance analysis, specifically
>>> the implication that the only performance cost is in building the new
>>> hidden class. That is not the case; everything that touches those objects
>>> is affected as well.
>>>
>>> Whether or not it's still the right way to accomplish what you're after,
>>> I wasn't venturing an opinion. I could probably come up with a benchmark
>>> showing that your WeakMap approach can be faster -- eg by only accessing
>>> the property once, but feeding the old and new versions of the object into
>>> code that executes many many many times (doing something that never looks
>>> at that property, but is now slightly slower because it isn't monomorphic).
>>> But I suspect that for practical usage, redefining the property *is* faster
>>> than a WeakMap.
>>>
>>> If I were to look beyond for other solutions for your problem, then I'm
>>> just speculating. Can decorators populate multiple properties once the
>>> expensive work is done?
>>>
>>> I really want to tell the VM what's going on. I guess if it knew that
>>> accessing a getter property would convert it into a value property, and
>>> that it was doing something that would access the getter, then it could
>>> know to use the outgoing shape instead of the incoming shape. If only it
>>> knew that the getter was pure... but that way lies madness.
>>>
>>> Given that most code that would slow down would also trigger the lazy
>>> defineProperty(), it's really not going to be that much of an issue. Any
>>> access after the first will see a single shape.
>>>
>>> meh. Just take the perf hit, with awareness that you may be triggering
>>> slight slowdowns in all users of that object. Or you might not. I doubt
>>> it'll be that big, since you'll probably just end up with an inline cache
>>> for both shapes and there won't be all that much to optimize based on
>>> knowing a single shape.
>>>
>>> Oh, and I think I was wrong about property enumeration order. The
>>> properties already existed, so defineProperty shouldn't modify the order
>>> IIUC. (I am awful with language semantics.)
>>>
>>> On 9/11/17 2:48 PM, Andrea Giammarchi wrote:
>>> Steve it's not solved in any other way. Even if you use a WeakMap with
>>> an object, you gonna lazy attach properties to that object.
>>>
>>> I honestly would like to see alternatives, if any, 'cause so far there
>>> is a benchmark and it proves already lazy property assignment is around 4x
>>> faster.
>>>
>>> So, it's easy to say "it's not the best approach" but apparently hard to
>>> prove that's the case?
>>>
>>> Looking forward to see better alternatives.
>>>
>>>
>>> On Mon, Sep 11, 2017 at 8:15 PM, Steve Fink <mailto:sphink at gmail.com>
>>> wrote:
>>> On 9/11/17 5:36 AM, Matthew Robb wrote:
>>> > I think it's irrelevant if internally VMs are not too happy. VMs are
>>> there to solve our problems, not vice-versa ;-)
>>>>>> This ^​ is very important for everyone to get on board with. Regardless
>>> the cost should be negligible as the shape is only changing at the point of
>>> delayed init. This will cause, for example V8, to deop the object and have
>>> to build a new hidden class but only the one time. I guess it would
>>> potentially be interesting to support an own property that when undefined
>>> would delegate up the proto chain.
>>>
>>> (I don't know, but) I would expect it to be worse than this. The shape
>>> is changing at the point of delayed init, which means that if an engine is
>>> associating the possible set of shapes with the constructor (or some other
>>> form of allocation site + mandatory initialization), then that site will
>>> produce multiple shapes. All code using such objects, if they ever see both
>>> shapes, will have to handle them both. Even worse, if you have several of
>>> these delayed init properties and you end up lazily initializing them in
>>> different orders (which seems relatively easy to do), then the internal
>>> slot offsets will vary.
>>>
>>> You don't need to bend over backwards to make things easy for the VMs,
>>> but you don't want to be mean to them either. :-)
>>>
>>> Not to mention that the observable property iteration order will vary.
>>>
>>> On Mon, Sep 11, 2017 at 7:09 AM, Andrea Giammarchi <mailto:
>>> andrea.giammarchi at gmail.com> wrote:
>>>
>>> Hi Peter.
>>>
>>> Unless you have a faster way to do lazy property assignment, I think
>>> it's irrelevant if internally VMs are not too happy. VMs are there to solve
>>> our problems, not vice-versa ;-)
>>>
>>> Regards
>>>
>>>
>>>
>>> On Mon, Sep 11, 2017 at 11:54 AM, peter miller <mailto:
>>> fuchsia.groan at virgin.net> wrote:
>>> Hi Andrea,
>>> ```
>>> class CaseLazy {
>>>   get bar() {
>>>     var value = Math.random();
>>>     Object.defineProperty(this, 'bar', {value});
>>>     return value;
>>>   }
>>> }
>>> ```
>>>
>>> Doesn't this count as redefining the shape of the object? Or are the
>>> compilers fine with it?
>>>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> mailto:es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>>
>>>
>>>
>>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>>
>> _______________________________________________
>> 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/20170916/ca890c48/attachment-0001.html>


More information about the es-discuss mailing list