When writing deep data structure we generally need to do something like
cache[server] ??= {}
cache[server][channel] ??= {}
cache[server][channel][service] = options
This is generally really verbose and we can already compact this by putting each part in parenthese :
((cache[server] ??= {})[channel] ??= {})[service] = options
but for each level of null coalescing we need to put the parentheses, so I propose to create the nullish coalescing ternary which don't need parentheses
cache[server]??{}:[channel]??{}:[service]=options
In this case adding {}
or []
just after ?? would permit to indicate what's expected to assign if nullish, but we could apply anything we want.
No offence, but that last line is super unreadable :D
I too wanted this in more than one language. Perhaps even before I learned that Perl does this automagically, without special syntax. In languages without a concise way to do it, I always end up with a function like this:
function autovivify(obj, ...keys) {
let o = obj
for (const k of keys) {
o = o[k] ??= {}
}
return o
}
autovivify(cache, server, channel)[service] = options
I don't see why you would want to create anything other than an object in the middle of the sequence, and allowing arbitrary expressions there would just lead to even less readable mess. I think that if autovivification were to be supported, it'd better be limited, covering only the most obvious cases (like the one you described), with minimal amount of clutter. Such as a yelling assignment operator:
cache[server][channel][service] !!= options
// equivalent to the autovivify example above