Proposal: Forced Chaining Operator "!."

Ben Wiley therealbenwiley at gmail.com
Tue May 5 13:12:05 UTC 2020


Sorry to show up late but just wanted to point out that shipping this
feature with the ! symbol would break TypeScript, which has this operator
but only at compile time for forcing the compiler to believe that a
nullable value will be non-null at the time of execution (assuming you have
some information the compiler doesn't). It has no runtime effect of
creating objects.

Le mar. 5 mai 2020 07 h 36, Tobias Buschor <tobias.buschor at shwups.ch> a
écrit :

> I think that would work, but the many nested brackets bother me.
>
> Am Mo., 27. Apr. 2020 um 14:23 Uhr schrieb Naveen Chawla <
> naveen.chwl at gmail.com>:
>
>> Can someone confirm if the following nullish coalescing assignment
>> operator proposal example would work for this, or would it produce some
>> other kind of result?:
>>
>> ```js
>> (((table ??= {}).user ??= {}).id ??= {}).type = 'int'
>> ```
>> Regardless, I'm not a TC39 member but I would definitely be against
>> forcing a type during assignment if "not already that type", as recommended
>> in the original post. I think this could be a source of serious bugs in
>> particular when an existing type structure has been miscalculated by the
>> person using that "force type" operator. So regardless, I would prefer any
>> shorthand to only assign to object/array etc. "if nullish". This would
>> raise errors if already of an unexpected type, but I would much prefer that
>> over forcing a new structure where an existing one already exists (and
>> overwriting data).
>>
>> On Mon, 27 Apr 2020 at 10:17, Max Fechner <max.fechner at gmail.com> wrote:
>>
>>> 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-bounces at mozilla.org> on behalf of Jacob
>>> Bloom <mr.jacob.bloom at gmail.com>
>>> *Date: *Monday, 27April, 2020 at 02:23
>>> *To: *es-discuss <es-discuss at 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.bloom at 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 <joeedh at 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.bloom at 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 <tshinnic at 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.buschor at 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 instanceOf Object) ) 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 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
>>>
>>> _______________________________________________
>>> 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
>>
>
>
> --
> Freundliche Grüsse
> Tobias Buschor
>
> schwups GmbH
> Hauptstr. 33
> 9424 Rheineck/SG
>
> +41 76 321 23 21
> _______________________________________________
> 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/20200505/b8750a1f/attachment-0001.html>


More information about the es-discuss mailing list