Reified lvalue (was: Re: Extensible destructuring proposal)

Herby Vojčík herby at mailbox.sk
Wed Aug 19 13:53:14 UTC 2015



Bergi wrote:
> Samuel Hapák schrieb:
>
>> The main idea is, that if object defines `Symbol.get` method, it gets
>> used to access properties of object instead of `[]` when destructuring.
>
> Aw, when I read "extensible destructuring" I had hoped to see an
> extension to the destructuring syntax, not to see how semantics of
> destructuring objects are changed.
>
> What do you think about extractor functions, like in Scala
> <http://www.scala-lang.org/old/node/112>?
> Instead of `unapply` or `unapplySeq` methods we'd probably use an
> `@@extractor` (`Symbol.extractor`) method or so, allowing us to do
>
> let Map({a, b, c}) = myMap;
>
> let List(a, b, c) = myList;
>
> const Map({author: Map({name: {first, last}, birthdate})}) = book;
>
> which would desugar to
>
> let [{a, b, c}] = Map[Symbol.extractor](myMap);
>
> let [a, b, c] = List[Symbol.extractor](myList);
>
> const [{author: __author}] = Map[Symbol.extractor](book);
> const [{name: {first, last}, birthdate}] = Map[Symbol.extractor](__author);
>
> where each extractor method would return an Iterable that is assigned to
> the "arguments" of the extractor. (A Proxy to lazily destructure object
> literals in there is a good idea, thanks @Claude).
>
> This would even allow us to call functions on destructuring, think about
> module imports:
>
> // a.js
> export default function factory(options) {
>> return moduleInstance;
> }
>
> // b.js
> const NoOptions = {
> [Symbol.extractor](factory) { return [factory()]; }
> };
> const WithOptions = (...args) => ({
> [Symbol.extractor](factory) { return [factory(...args)]; }
> });
>
> import NoOptions(A) from "a";
> import WithOptions("config")(A) from "a";
> // A === moduleInstance
>
> What do you think about that?

Nice, but as Samuel mentioned, you need to actually transform the data 
so it can be fed to stock destructurer.

What I came up is the idea of "reified lvalue", the object that 
describes the (complex, destucturing) lvalue used for assignment (for 
example as the list of simple expression assignments, internally); and 
that such object could be transformed.

Like (very rough examples; just an idea, not the spec):

   let a = 4;

   outer a <- input


   let {a,c:{b}} = foo;

   outer a <- input.a
   tmp0 <- input.c
   outer b <- tmp0.b


   let {a,c:Map({b})} = foo;

   Map[Symbol.lvalue] gets "outer b <- input.b" and transforms it to 
"outer b <- input.get('b')", so the result would be:

   outer a <- input.a
   tmp0 <- input.c
   outer b <- tmp0.get('b')


   let Map(a,c:Map({b})) = foo;

   Map[Symbol.lvalue] get the above descriptor and transforms it to

   outer a <- input.get('a')
   tmp0 <- input.get('c')
   outer b <- tmp.get('b')

If things like Map[Symbol.lvalue] would be frozen (or just speculatively 
supposed not to be mutated), this can as well be done at compile time, 
so the resulting code could stay fast.

> Bergi

Herby


More information about the es-discuss mailing list