user663031
user663031

Reputation:

Swap tuple elements with destructuring assignments

I thought to swap the elements of a tuple in place using destructuring assignment as follows:

var a = [1,2];
[a[1], a[0]] = a;

However, this yields [1, 1].

Babel compiles this as

a[1] = a[0];
a[0] = a[1];

I would have thought this should be compiled as

let tmp0 = a[0];
let tmp1 = a[1];
a[0] = tmp1;
a[1] = tmp0;

Traceur behaves identically to babel. So I guess this is the specified behavior?

I want to swap the two elements in place. So is the only way...

let tmp = a[0];
a[0] = a[1];
a[1] = tmp;

But I thought the above was what destructuring assignment was supposed to let me avoid having to do.

I'm perfectly capable of reversing the order of the two elements of the array, so that is not my question. I could do something as simple as a.push(a.shift()), which meets the criteria of the swapping being in-place.

I'm most interested here in why destructuring doesn't work the way it seems that it ought to.

Upvotes: 6

Views: 1176

Answers (5)

Mulan
Mulan

Reputation: 135207

I'd just use a function to do this -

const swap = ([a,b]) => [b,a];

console.log(swap([1,2])); // [2,1]

Of you can swap in place -

const a = [1,2];

[a[1], a[0]] = [a[0], a[1]];

console.log(a); // [2,1]

Upvotes: 8

Jeremy Larter
Jeremy Larter

Reputation: 558

This works in Firefox which supports destructuring:

(function () {
  "use strict";

  var a = [0, 1];
  [a[1], a[0]] = [a[0], a[1]];
  console.log(a);//[1, 0]
}());

Upvotes: 2

Bergi
Bergi

Reputation: 664385

I would have thought this should be compiled as

let tmp0 = a[0];
let tmp1 = a[1];
a[0] = tmp1;
a[1] = tmp0;

No, the values don't get retrieved before they are assigned. Or neither is a copy of a made from which the values are retrieved. There only is a single reference to the array; your code rather desugars to

{
    const tmp = a;
    a[1] = tmp[0];
    a[0] = tmp[1]; // here, tmp[1] has the "wrong" value because a===tmp
}

or in fact, it desugars to an iterator that iterates the array while the left-hand-side references in the […] are assigned to.

Upvotes: 4

Oriol
Oriol

Reputation: 288080

As an alternative, you can use slice:

var a = [1,2];
[a[1], a[0]] = a.slice();
a; // [2,1]

Upvotes: 3

Kip
Kip

Reputation: 558

How about this:

var a = [1,2];
a = a.reverse();

Upvotes: 3

Related Questions