Thoughts on expression matching in JavaScript

kraftdorian

Damian

Posted on May 4, 2021

Thoughts on expression matching in JavaScript

Context

Just one word - curiosity. It stays with me through the whole learning process of programming.

When I met Erlang's built-in mechanism of expression matching I couldn't stay inert and immediately started comparing it to what I know in JavaScript.

What does JavaScript offer

Let's consider these examples when it comes to matching some expressions.

Example 1 - if

What are we doing here is we describe how our expected value should look like, not to provide something to match.

For me, it also lacks readability because conditions are mostly used to express the logic and perform various value checks, not to directly deal with the data.

const response = {data: 'foo'};
if (response === true) {}
else if (response === 1) {}
else if (response.data === 'foo') {}
else if (conditionN) {}
// ...
else {}
Enter fullscreen mode Exit fullscreen mode

Example 2 - switch/true

Similar to the conditions listed above we still describe the value we want to match.
However, for me, it is more readable.

const response = {data: 'foo'};
switch(true) {
  case response === 1: break;
  case response.data === 'foo': break;
  case conditionN: break;
  // ...
  case true: break;
}
Enter fullscreen mode Exit fullscreen mode

Example 3 - switch

Here, things start to get more interesting.

const response = {data: 'foo'};
switch(response) {
  case {data: 'foo'}:
    console.log('matched!');
    break;
}
Enter fullscreen mode Exit fullscreen mode

This won't work because of the way JavaScript compares the values.
I don't want to list all scenarios below, but you can learn more here.

{data: 'foo'} === {data: 'foo'} // false
{data: 'foo'} == {data: 'foo'} // false
Object.is({data: 'foo'}, {data: 'foo'}) // false
Object.is(response, response) // true
Enter fullscreen mode Exit fullscreen mode

Example 4 - RegExp

Let's give it a try. It's the closest solution I can think of in terms of expression matching.

const response = {data: "foo"};
/^{"data":(.+)}$/.exec(JSON.stringify(response)); // ["{"data":"foo"}", ""foo"", ...
Enter fullscreen mode Exit fullscreen mode

It's nice but has some cons. How about a tailored solution?

What does Erlang offer?

Let's just have a look at this code.

Response = {{data, "foo"}}.
case Response of
  {{data, "foo"}} -> io:fwrite("matched!");
  {{data, Data}} -> io:fwrite("matched ~p!", [Data]);
  1 -> io:fwrite("1");
  _ -> io:fwrite("default match")
end.
% matched!
Enter fullscreen mode Exit fullscreen mode

We don't even know some values in the match expression but Erlang is still able to find them.

Experimenting with JavaScript implementation

After a couple of days where I couldn't write anything worth sharing, I have some POC, that you can find here.

const response = {
  status: false,
  message: "Error",
  some_dynamic_key: null
};
const template = {
  status: "<<expr@Status>>",
  message: "<<expr@Message>>",
  ["<<expr@DynamicKey>>"]: "<<expr@DynamicKeyValue>>"
};
const result = match_val(response, template);

console.log(result); // [true, [false, 'Error', 'some_dynamic_key', null]]
Enter fullscreen mode Exit fullscreen mode

Summary

Overall, I think that an expression matching mechanism in JavaScript would be nice to have for specific use-cases as we have in functional programming.

Also, it's always nice to learn new things and how they could have been implemented.

Article cover photo by Michael Dziedzic
💖 💪 🙅 🚩
kraftdorian
Damian

Posted on May 4, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related