Declaration types inside destructuring declarations

# Bob Myers (7 years ago)

Totally minor, but

const {a, b} = o;
b = 1;

Complains that b is const and can't be assigned.

let {a, b} = o;
b = 1;

Now lint complains that a is never modified, and ought to be const.

So I would like to write:

const {a, let b} = o;
b = 1;

or alternatively

let {const a, b} = o;
b = 1;
# Jordan Harband (7 years ago)
const { a } = o;
let { b } = o;
b = 1;

seems like a much simpler workaround than adding this complexity to the language.

Given your two examples, I'd find it bizarre for one to work and the other not, so we'd want to support both. It also raises the question of declaration-less assignments - ({ a, b } = o); could become ({ const a, let b } = o);?

# Steve Fink (7 years ago)

On 07/03/2017 12:25 PM, Jordan Harband wrote:

const { a } = o;
let { b } = o;
b = 1;

seems like a much simpler workaround than adding this complexity to the language.

I dunno. I've wanted this numerous times. The use case is really

const { a, let b } = complexExpression();

A typical scenario is when I'm splitting something up and returning the parts, and I want one for a short-lifetime const and the other to update a state variable.

On the other hand, it reads pretty oddly to me, and I would probably vote against complicating the parsing for this anyway.

{ const a, let b } = complexExpression();

reads a little better to me. Another alternative would be

const { a } = let { b } = complexExpression();

and I suppose that suggests a better workaround than what I normally use. Workaround:

let b; const { a } = { b } = complexExpression();

Or with arrays:

let b; const [ a ] = [ ,,b ] = complexExpression();

Tangent: it would be nice to have a "don't care" value; those commas are hard to spot. 'undefined' doesn't work and is too long anyway. _ is ok if you predeclare with let _; but you can only use it once. This won't work:

const [ _, a, _, b ] = o;

nor will

let _; const [ _, a ] = [ b, _, c ] = foo();

I guess it's better to not predeclare with let, but then you pollute the global object, and you still can't use it with

const [ _, a ] = foo(); const [ _, b ] = bar();

# Oriol _ (7 years ago)

And why not just use

const result = complexExpression();
const {a} = result;
let {b} = result;

and with arrays:

const result = complexExpression();
const a = result[0];
let b = result[2];

If nothing else references result, it can be garbage-collected.

I don't see the need to add new syntax for this.

# Steve Fink (7 years ago)

On 07/06/2017 10:39 AM, Oriol _ wrote:

And why not just use

const result = complexExpression();
const {a} = result;
let {b} = result;

and with arrays:

const result = complexExpression();
const a = result[0];
let b = result[2];

That's exactly what I do now. It's tolerable, but inelegant. I suspect it's also not identical semantics, with getters being called different numbers of times and things, which is mostly irrelevant but could matter for optimizations. Or maybe destructuring assignment is specced to be identical, I don't know.

The array ones are pretty ugly. If I'm packing multiple return values into an array, then the numeric indexes are pure noise.

const [a, _, b] = complexExpression();

is way better than

const a = result[0]; const b = result[2];

IMHO, and similarly for objects. Not to mention

const [a, [b, c], d] = complexExpression();

My coding aesthetic is to have as much of the program text as possible be stuff related to the problem I'm solving, with some amount of unavoidable wiring (the amount varies widely by language). A temporary like this requires a name, which with my style implies that it is significant enough to deserve a name. A reader/reviewer must come to the realization that it's just a workaround for a language deficiency and not something semantically meaningful, which is a small speed bump to understanding. (And in fact, even if the facilities were available, I would at times introduce an intermediate variable anyway, if I felt it aided understanding of the semantics. The presence or absence would be a conscious choice based on conveying meaning to the (human) reader, even though the computer couldn't care less. If there's a good name for the intermediate, it should probably be there, and if not, it shouldn't.)

In the whole scheme of things, this is minor enough that I wouldn't personally argue for any special syntax here, but I could support something if others were interested and it had clean syntax.

If nothing else references result, it can be garbage-collected.

In the absence of optimizations (scalar replacement), there's no GC difference here. complexExpression() is going to create and return a garbage-collectable object whether you bind it to a name or not. The optimization is certainly simpler and I would guess much more likely to be applied if you don't have the temporary, though.