There has to be a better pattern than returning the "foo()" if the baz
property doesn't exist.

I'm curious what you would want to do with the resulting "foo()" anyway. I
can imagine a flow where I want "bar", and it doesn't exist it doesn't. I
cannot imagine wanting the "foo()" in place of it. There is type
unpredictability in the result, so subsequent operations would normally
expected to be impossible without type-branching. Hence my question to you
about what you would typically want to do with the "foo()" if that was the
returned result.

On Sat, 7 Sep 2019 at 12:08, Andrea Giammarchi <[email protected]>
wrote:

> Interesting I forgot about that, but it wouldn't cover the "trap here" use
> case.
>
> foo().bar ?! what => what : what;
>
> I'd like to forward foo() here
>
> On Sat, Sep 7, 2019, 11:45 Michael Luder-Rosefield <[email protected]>
> wrote:
>
>> This is getting very reminiscent of my 'forwarding ternary' operator (or
>> whatever I called it) I suggested a couple of years ago. I believe you were
>> involved in the discussion, Andrea...!
>>
>> ```
>> const val = foo() ?!
>>   (x) => x.bar.baz :
>>   someFallbackValue;
>> ```
>>
>> On Sat, 7 Sep 2019, 10:17 Andrea Giammarchi, <[email protected]>
>> wrote:
>>
>>> To better answer, let's start dropping any direct access and put a
>>> payload in the mix.
>>>
>>> As example, in the `foo()?.bar.baz` case, you might end up having `null`
>>> or `undefined`, as result, because `foo().bar` existed, but `bar.baz`
>>> didn't.
>>>
>>> In the `foo()?.bar?.baz` case, you might end up having `foo().bar`,
>>> because `bar.baz` didn't exist.
>>>
>>> But what if you are not interested in the whole chain, but only in a
>>> main specific point in such chain? In that case you would have
>>> `foo()?.bar.baz ?? foo()`, but you wouldn't know how to obtain that via
>>> `foo()?.bar?.baz ?? foo()`, because the latest one might result into
>>> `foo().bar`.
>>>
>>> Moreover, in both cases you'll end up multiplying the payload at least *
>>> 2, while the mouse trap will work like this:
>>>
>>> ```js
>>> foo()<?.bar?.baz
>>> ```
>>>
>>> if either `foo().bar` or `bar.baz` don't exist, the returned result is
>>> `foo()`, and it's computed once. You don't care about `foo().bar` if
>>> `bar.baz` is not there, 'cause you want to retrieve `foo()` whenever you
>>> have a failure down the chain.
>>>
>>> Specially with DB operations, this is a very common case (abstraction
>>> layers all have somehow different nested objects with various info) and the
>>> specific info you want to know is usually attached at the top level bject,
>>> while crawling its sub properties either leads to the expected result or
>>> you're left clueless about the result, 'cause all info got lost in the
>>> chain.
>>>
>>> The `foo()<?.bar.baz` case is a bit different though, 'cause if
>>> `foo().bar` existed, there's no way to expect `foo()` as result, and if
>>> it's `bar` that you're after you can write instead `foo()?.bar<?.baz` so
>>> that if `baz` is not there, `bar` it is.
>>>
>>> This short-circuit the need for `??` in most cases, 'cause you already
>>> point at the desired result in the chain in case the result would be `null`
>>> or `undefined`.
>>>
>>> However, `??` itself doesn't provide any ability to reach any point in
>>> the previous chain that failed, so that once again, you find yourself
>>> crawling such chain as fallback, resulting potentially in multiple chains
>>> and repeated payloads.
>>>
>>> ```js
>>> // nested chains
>>> foo()?.bar.baz?.biz ?? foo()?.bar.baz ?? foo()?.bar;
>>>
>>> // mouse trap
>>> foo()?.bar<?.baz?.biz;
>>> ```
>>>
>>> Above example would prefer `foo().bar` if it exists, and if either
>>> `bar.baz` or `bar.baz.biz` returned `null` or `undefined`.
>>>
>>> I hope this clarifies further the intent, or the simplification, that
>>> such operator offers: it's a complementary hint for any optional chain, it
>>> doesn't have to be used, but when it does, it's visually semantic in its
>>> intent (at least to my eyes).
>>>
>>> Regards
>>>
>>>
>>>
>>>
>>> On Fri, Sep 6, 2019 at 11:20 PM Tab Atkins Jr. <[email protected]>
>>> wrote:
>>>
>>>> On Fri, Sep 6, 2019 at 8:04 AM Andrea Giammarchi
>>>> <[email protected]> wrote:
>>>> > Indeed I'm not super convinced myself about the "branching issue"
>>>> 'cause `const result = this?.is?.branching?.already` and all I am proposing
>>>> is to hint the syntax where to stop in case something else fails down the
>>>> line, as in `const result = this.?.is<?.branching?.too` to know that if any
>>>> other part is not reached, there is a certain point to keep going (which
>>>> is, example, checking that `result !== this`)
>>>>
>>>> Important distinction there is that ?. only "branches" between the
>>>> intended type and undefined, not between two arbitrary types. The
>>>> cognitive load between those two is significantly different.
>>>>
>>>> In particular, you can't *do* anything with undefined, so
>>>> `foo?.bar.baz` has pretty unambiguous semantics - you don't think you
>>>> might be accessing the .baz property of undefined, because that
>>>> clearly doesn't exist.
>>>>
>>>> That's not the case with mouse, where it's not clear, at least to me,
>>>> whether `foo<?.bar.baz` is doing `(foo.bar ? foo.bar : foo).baz` or
>>>> `foo.bar.baz ? foo.bar.baz : foo` or even `foo.bar ? foo.bar.baz :
>>>> foo`. All three seem at least somewhat reasonable, and definitely
>>>> *believable* as an interpretation!
>>>>
>>>> ~TJ
>>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> [email protected]
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>> _______________________________________________
> es-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es-discuss
>
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to