1

Given a function that accesses a property of a JavaScript object—

let useFoo x => Js.log x##foo;

useFoo {"foo": 10};

—is there a way to rewrite it to pattern match for the property?

I'd hoped that something like this would work, but the syntax is invalid:

let useFoo {"foo"} => Js.log foo;
ændrük
  • 782
  • 1
  • 8
  • 22

1 Answers1

4

There's no way to do this, and the reason for this is that Javascript objects - which are little more than mappings of keys to values - are handled using Reason's (ie. OCaml's) object-oriented system. In Reason/OCaml, you cannot pattern match over functions ie. if I have a record containing a lambda, I cannot pattern match over the result of applying that lambda:

type t = {foo: int => int};

let bar {foo} => foo 5;

Notice that I can pattern match and get the foo lambda out of the record, but I can't apply foo inside the pattern match -- I have to apply it to the argument '5' after I extracted it.

Here's the problem with objects: the only interface to objects in Reason is via their public methods. Methods are like lambdas, except that their first argument is always self, which is the object itself. So every time we access x##foo, we're really dispatching the foo method, feeding it x as an argument, and getting the result back. Just as we can't pattern match in Reason over function application, we can't pattern match over objects either, since objects are just collections of functions that get applied automatically.

Bluddy
  • 104
  • 2
  • Just to add to this, JS objects are typed as lifted OCaml objects, but the syntax for creating JS objects in Reason is actually sugar for something quite different. `{ "foo": 42 }` desugars to `[%bs.obj { foo = 42 }]`, which is a syntax extension being passed a _record_. So even if you could pattern match on objects, the syntax would need to translate to both objects and records depending on where it's used. – glennsl Sep 06 '17 at 21:07