fail-fast object destructuring (don't add more slop to sloppy mode)

Herby Vojčík herby at mailbox.sk
Wed Jan 2 13:25:46 PST 2013



Brendan Eich wrote:
> Herby Vojčík wrote:
>> Brendan Eich wrote:
>>> Herby Vojčík wrote:
>>>> Brendan Eich wrote:
>>>>> You're right, this implies destructuring binding forms behave in a way
>>>>> that I flagged as possibly not wanted:
>>>>>
>>>>> let {p?: {q: r}} = o;
>>>>>
>>>>> would bind r to undefined for any o that doesn't have a p or that does
>>>>
>>>> In my view it binds to Nil (but it is falsey, == null etc., typeof
>>>> 'undefined' so it should work).
>>>
>>> I don't think we should multiply risk by coupling destructuring (which
>>> is in ES6) to Nil (an unproposed strawman) at this point.
>>>
>>> In theory and ignoring schedule and order of work, we could, and doing
>>> so has some symmetry (or really some duality) with a Nil-under-the-hood
>>> for ?. as existential operator. This is not a strong motivation in my
>>> view.
>>>
>>> Also, would you really produce nil not undefined only for patterns where
>>> ? was used and the pattern irrefutably succeeded because of a missing
>>> property, and otherwise (no ?-pattern involved) bind r to undefined? IOW
>>>
>>> let {p: {q?: r}} = {p: {s: 42}};
>>>
>>> binds r to nil, while
>>>
>>> let r = {p: {s: 42}}.r;
>>
>> You meant let r = {p: {s: 42}}.p.q?, didn't you?
>
> Er, yes! Sorry about that.
>
>> This binds r to nil as well.
>
> Confusion. Let me write it out to be sure we are talking about the same
> thing:
>
> let r = {p: {s: 42}}.p.q;
> binds nil to r? That's not backward compatible.

Sorry, I did wrote it so it could lead to confusion.
Let me try to explain better.

	(1)	let {p: {q?: r}} = {p: {s: 42}};
		// me: r = Nil, you: ???, probably undefined

	(2)	let r = {p: {s: 42}}.p.q?;
		// me: r = Nil, you: ???, probably undefined

	(3)	let {p: {q: r}} = {p: {s: 42}};
		// r = undefined (of course)

	(4)	let r = {p: {s: 42}}.p.q;
		// r = undefined (of course)

You compared (1) to (4). I would it is comparing apples to oranges, and 
that (1) and (2) or (3) and (4) should be compared.

>> Yes. But one of the problems mentioned on this thread was ARB's "It's
>> not composable".
>
> s/composable/compositional/
>
> That was about CoffeeScript's semantics based on transcompilation, which
> I showed a few messages back. From Andreas's comments as captured in the
> minutes:
>
> """
>
> ARB: This is non-compositional
>
> o = {}
> r = o?.p.q.r
> r = (o?.p).q.r
> r = o?.p.q.r()
>
> Results in…
>
> var o, r;
> o = {};
> r = o != null ? o.p.q.r : void 0;
> r = (o != null ? o.p : void 0).q.r;
> r = o != null ? o.p.q.r() : void 0;
>
> Non-starter.
>
> """
>
>
>> With internal-nil-exposed-undefined, these are different:
>>
>> (p.q?).r
>> p.q?.r
>>
>> With nil-reified, those are identical.
>
> Yes, I already agreed (three times :-|) that nil rescues ?. from the
> condemnation ARB heaped on the CoffeeScript semantics.

Sorry, I wasn't after this. It just seems there are still some 
misunderstadings...

> That's not relevant to what we were just arguing about though: whether
> nil rather than undefined should be an observable result of either

Now I am confused.
For (p.q?).r to be same as p.q?.r, (p.q?) must return reified Nil, not 
undefined. I was at the impression you say "Nil at the background, but 
whenever it becomes observable, it should be changed to undefined". That 
means p.q? returns undefined, and (p.q?).r fails.

Or do you mean (1) and (2) from above are not to be equivalant ((1) Nil, 
(2) undefined)?

Or something completely different?

> destructuring or (you seemed to say just above) property gets on plain
> old objects!

No, that was a misunderstanding.

> /be

Herby


More information about the es-discuss mailing list