How about something like

table{}.user{}.id{}.type = ‘int’

this syntax could be used for arrays, too:

table{}.userList[].push(‘Jane Doe’)



From: es-discuss <es-discuss-boun...@mozilla.org> on behalf of Jacob Bloom 
<mr.jacob.bl...@gmail.com>
Date: Monday, 27April, 2020 at 02:23
To: es-discuss <es-discuss@mozilla.org>
Subject: Re: Proposal: Forced Chaining Operator "!."

(Sorry for the triple-post, I keep pondering this proposal) Come to think of 
it, you could do something pretty similar with the `??=` operator from the 
logical assignments proposal:

```javascript
(((table ??= {}).user ??= {}).id ??= {}).type = 'int';
```

The main difference being that it tests for nullishness instead of whether the 
LHS is a non-null object, but I think that's within the spirit of the original 
proposal. It also lets you set a custom default value (like the "getsert" 
function above). The shortfall of course is the accumulating parentheses

On Sat, Apr 25, 2020 at 8:08 PM Jacob Bloom 
<mr.jacob.bl...@gmail.com<mailto:mr.jacob.bl...@gmail.com>> wrote:
Is the Perl syntax opt-in like the proposed operator? Or does it happen on all 
accesses to nulls? If it's opt-in in JS, then it doesn't seem to me that it'd 
cause too much unexpected behavior, though it could be argued that it's ripe 
for abuse by new devs trying to avoid errors.

Something that might be a more generalized middle ground (and could later 
assist in transpiling the !. operator) is a "getsert" (?) method in the 
standard library that takes a default value and sets it on the parent object if 
that property is currently unset:

```javascript
Object.getsert = (obj, identifier, defaultvalue) => {
  if (!(identifier in obj)) obj[identifier] = defaultvalue;
  return obj[identifier];
}

const table = {};
console.log('before getsert:', table.user); // undefined
console.log('during getsert:', Object.getsert(table, 'user', 5)); // 5
console.log('after getsert:', table.user); // 5
```

...I have concerns about such a method's usability though, since a getsert is 
far more verbose than a normal get. It'd be more convenient on Object.prototype 
(e.g. `table.getsert('user', 5)` ), but I assume that's a no-go.

Oh also, I think the proposed syntax would collide with TypeScript's non-null 
assertion operator 
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator
 -- I don't know to what degree that's a concern when proposing new JS syntax

On Sat, Apr 25, 2020 at 3:00 PM Joe Eagar 
<joe...@gmail.com<mailto:joe...@gmail.com>> wrote:

Anyone have ideas on more examples? It’s tempting to make a transpiler plugin 
to see how it works in practice, but I’d like to see more examples first. Thanks

On Sat, Apr 25, 2020 at 1:12 PM Jacob Bloom 
<mr.jacob.bl...@gmail.com<mailto:mr.jacob.bl...@gmail.com>> wrote:
Maybe it would be less footgunny to support autovivification in a more 
class-based way, like Python does?

```javascript
class AutoVivArray extends Array {
  [Symbol.getMissing](identifier) {
    /* if we're here, identifier is not an ownProperty
     * and is nowhere on the prototype chain */
    this[identifier] = new Whatever();
    return this[identifier];
  }
}
```

Though I can't see how that's much more useful than Proxies besides saving you 
a little boilerplate

On Fri, Apr 24, 2020 at 3:23 PM Thomas Shinnick 
<tshin...@gmail.com<mailto:tshin...@gmail.com>> wrote:
You are describing Perl's autovivification feature. Also possible (in that 
syntax) for arrays and mixed object/array chains. I liked it, but many saw it 
as a footgun. There was even a compile time module to turn off the feature, if 
the coder wanted more caution. Having mentioned Perl I will assume this is DOA?

On Fri, Apr 24, 2020, 14:36 Tobias Buschor 
<tobias.busc...@shwups.ch<mailto:tobias.busc...@shwups.ch>> wrote:
Since we now have the "Optional Chaninig Operator" , perhaps a "Forced Chaining 
Operator" would also be worth considering.
I, personally, could use it:

    let table;
    table!.user!.id!.type = 'int'

will evaluate to:

    let table;
    if ( ! ( table instanceOf Object) ) table = {};
    if ( ! ( table.user instanceOf Object) ) table.user = {};
    if ( ! ( table.user.id<http://table.user.id> instanceOf Object) ) 
table.user.id<http://table.user.id> = {};
    table.user.id.type = 'int';

Also to be noted:
Sometimes a fallback to `Object.create(null)` or something other might be 
desirable.
But since `{}` is syntactical sugar for `Object.create(Object.prototype)`, this 
would be consistent.

_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to