Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
A case study on destructuring and pattern matching.
branch: master

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
README.md

README.md

Destructuring is one of the most powerful features of ES6. It allows for painless assignment of variables, but it could be so much more.

Destructuring is pattern matching. You can see this in one of the most shopped around examples of destructuring, flipping context.

var a = 1,
    b = 2;
console.log([b, a] = [a, b]);

Inherently this operation is matching a pattern.

In spyder monkey (one of the few engines supporting destructuring) it returns the matched array. This can be a useful tool.

Consider the following statement:

if (i = true) {
  console.log('this passes');
}

The implicit value is obvious in left hand assignment. It is the value of i. With a destructured statement the value is less implicit, but logical to infer.

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

Now consider the following:

([a, b] = [1, 2]).length;// true, all values have been fufilled
([a, b] = [1]).length == 2;// false, all values have not been fufilled

Rest parameters get a bit more complicated, since a rest parameter will return an empty array when no value is present:

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

Sadly length fails to provide any significant test of pattern fufillment. length again fails in the case of arrays with undefined values.

var x = [];
x[0] = 1;
x[2] = 3;
([a, b, c] = x).length;// 3

With this in mind a testing operator needs to be implemented, so we can get the full power of pattern matching. I propose the ?= operator as an existential pattern matcher.

[a, b] ?= [1, 2];// true
[a, b] ?= [1];// false
[a, ...rest] ?= [1, 2];// true
[a, ...rest] = [1];// false
var x = [];
x[0] = 1;
x[2] = 3;
[a, b, c] ?= x;// false

?= providing let style assignment would further its usefulness.

if ([x, ...rest] ?= [1, 2, 3, 4]) {
  console.log(rest);
}

In this context rest parameters could be expanded to include an unassigned rest.

[a, ...] ?= [1, 2];// true
[a, ...] ?= [1];// false

With destructured pattern matching (and tail call optimization) we could implement elegant recursive functions.

function reverse (a) {
  if (a.length < 1) {
     return [];
  } else if ([x, ...rest] ?= a) {
     return reverse(rest).concat(x);
  }
}

I have excluded the use of object destructuring for simplicity, but the concept easily transfers:

if ({parent: {child: {name: n}}} ?= obj) {
  console.log('child has a name');
}
Something went wrong with that request. Please try again.