so *maybe* we'll come back...
On Mon, Sep 9, 2019 at 10:04 AM Andrea Giammarchi <
[email protected]> wrote:
> `require("module")<?.default` is the easiest use case for this, as
> initially explained.
>
> `db.get(SQL)<?.rows?.[0]` the most common use case, for queries you know
> that won't fail but might not return the desired result, so that you end up
> holding the top most object with all the informations, instead of simply
> ending up with undefined. This works well with destructuring too.
>
> ```js
> const {rowsCount, id, name, email} = db.get(SQL)<?.rows?.[0];
> if (rowCounts === 0)
> askUserToRegister();
> else
> showUserDetails();
> ```
>
> As mentioned, there is a module that let you explicitly use this operator
> through a callback that tries to be as safe as it can (void after first
> `.trap` access + self clean on next microtask), so manye we'll come back to
> this discussion once we all understand the use case and why it's actually
> very useful in some circumstance.
>
> Regards
>
>
>
> On Sat, Sep 7, 2019 at 1:23 PM Naveen Chawla <[email protected]>
> wrote:
>
>> 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