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