tc39 / proposal-optional-chaining

https://tc39.github.io/proposal-optional-chaining/
4.94k stars 75 forks source link

Dot after question mark #5

Closed madskonradsen closed 5 years ago

madskonradsen commented 7 years ago

I'm very very glad to see this become resurrected. One thing I'm curious about is why you chose to have a dot after the question mark in case of function invocation and why you have a dot between question marks and square bracket notation. It seems strange to me, but perhaps i'm too biased by having written too much CoffeeScript.

a?.()
a?.[b]
claudepache commented 7 years ago

@levithomason

IMHO, there should some criteria for reaching a conclusion to this convo. Ideas?

The proposed conclusion of the main author of the proposal (myself) is #34, dated from few days ago. At this point, I’m waiting for eventual comments or objections before possibly proceeding.

levithomason commented 7 years ago

Very cool. I agree entirely and I've left my support there. I will bow out of this issue now assuming #34 is the answer.

hax commented 6 years ago

I suppose I could get used to something like ?!./?![]/?!(), which vaguely parallels TypeScript's non-null assertion (expression!).

I like this idea, but unfortunately ?![] / ?!() still conflict with ? : operator. Change the order (!?) may be ok.

But why not just use !. / ![] / !() ? It's short and easy to remember and nullish-coalescing can still use ??, and to be honest it's more consistent with ?? and avoid confusion like coffee.

The only problem is it break TS compatibility, but this is not the most important operator in TS, and TS can easily change to !!. / !![] / !!() .

caub commented 6 years ago

@claudepache

The goal of ?? is precisely to be able to write a??[b] and a??(b).

I like levithomason's proposal, a function call is really distinct from a property accessor, they shouldn't have the same form

Also why not a.?b (the dot before)?

hax commented 6 years ago

@caub .? is possible, but what about x[y]? I remember there was x[?y] option in es-discuss, but looks too weird.

TheNavigateur commented 6 years ago

What about just .?:

a..b
a.[b]
a.(b)

To me it looks prominent, and is quick to type and remember.

If you see an obvious case where it's not backwards compatible, I'm curious to know what that is

caub commented 6 years ago

@TheNavigateur it doesn't convey much the meaning of 'optional', and also confusing with 2..toString() number literal

claudepache commented 6 years ago

@caub

and also confusing with 2..toString() number literal

2..toString() is not an issue, because the proposed (2)..toString() is observably equivalent to (2.).toString() (number literals are never null).

caub commented 6 years ago

or just (2).toString(), I just meant visually confusing

littledan commented 6 years ago

@claudepache Even if it's not an issue formally, this still seems a bit confusing for developer intuition. I like how the current proposal includes ?, which creates parallelism with the ?? proposal and this feature in other languages.

TheNavigateur commented 6 years ago

If ? must be in the operator then how about ?> ?

a?>.b
a?>[b]
a?>(b)
littledan commented 6 years ago

@TheNavigateur Actually, I like that one!

ljharb commented 6 years ago

Looks pretty similar to pipeline tho.

rattrayalex commented 6 years ago

There's another thread that talks about the syntax a bit more: #34

In an informal poll, ??. seemed to be popular: https://github.com/tc39/proposal-optional-chaining/issues/34#issuecomment-333413308

In any case, should this issue be folded into that one?

TheNavigateur commented 6 years ago

I think > conveys "propagate in this direction" (like an arrow) and I think the shape of ?> is distinctive enough from the |> (function call pipeline) and +> (function composition) operators as to be immediately distinguishable from them. All the other proposals overlap with other operators in at least some way. I just think this one probably offers the least friction and best clarity.

Mouvedia commented 6 years ago

Here's a proposal which resolves the cases that were considered problematic. It requires to surround the expression with parentheses if you want to use the bracket notation, that's it.

// a == null ? undefined : a.b
a?.b;

// (a == null ? undefined : a[d]) + c
(a?[d]) + c

// throws (missing the : part of the ternary)
a ? [d] + c;

// just a backward compatible ternary
a ? [d]+c : d;

// throws (missing the ? part of the ternary)
(a?[d])+c : d;

// throws
e ? a?[d]+c : d;
// OK
e ? (a?[d])+c : d;
// OK
e ? a ? [d]+c : d : f;
e ? (a ? [d]+c : d) : f;

The real beauty in that proposal is that you will have an early error in previous ES implementation because the closing parenthesis is not found before the ? or at the end of the ternary.

ljharb commented 6 years ago

That’s an unacceptable ergonomic cost - bracket access needs to be as seamless as dot access.

littledan commented 6 years ago

I'm not sure if I agree with @ljharb on this stance on ergonomics in general, but I don't see how adding parentheses addresses the grammar issue. You'd still have to read ahead to the closing paren to figure out whether this is ternary or optional chaining, wouldn't you?

pronebird commented 6 years ago

Not sure if it’s too hard to do a lookahead. But if we would have to do a lookahead then there is no need to use parens until ternary expression involved. Then I find it reasonable to use parens to disambiguate the ternary part from the optional chaining.

littledan commented 6 years ago

One of the concerns here, which ruled out ?[ normally, was allowing streaming parsers. Currently, in principle, JavaScript can be parsed by something which just works left to right, without multiple passes or backtracking. If you allow ?[ for optional chaining, you have to read ahead further in the expression to figure out what token you're talking about. It doesn't really help whether you force parens around it--parens are easy to match, but if you were willing to look ahead for a matching paren, you'd be able to look to the end of the statement too. The issue is looking ahead an arbitrary distance like that.

hax commented 6 years ago

Though ?> idea seems ok for current JS, I worry about it being conflict with the usage of <> in generic type (TypeScript/Flow) or JSX.

TheNavigateur commented 6 years ago

Might only be as much conflict as =>

rattrayalex commented 6 years ago

I'm not sure (a?[b]) would require a lookahead (just an extra bit of state in eg; parseConditional or equivalent and a node rewrite, as we do for eg object patterns). Most JS parsers currently require a lookahead anyway.

But I certainly agree with @ljharb that requiring parens would be unacceptable.

Perhaps discussion about ?> should move to #34.

Mouvedia commented 6 years ago

that requiring parens would be unacceptable

Wouldn't be the first time. cf https://github.com/tc39/proposal-optional-chaining/issues/5#issuecomment-321973312

ljharb commented 6 years ago

@Mouvedia that should have been unacceptable, and could have been avoided. That's not a precedent to knowingly add another huge footgun along with new syntax.

Mouvedia commented 6 years ago

There's some kind of poll on #51.

vcicmanec commented 6 years ago

Why not think about it as a "?." operator with its own, slightly different, semantics, rather than spending a few years coming up a with a pristine proposal that won't satisfy all anyway?

cshaa commented 6 years ago

Why don't we just close this issue and stick to the current proposal?
It's easy to read (less visual clutter than ??), unambiguous and doesn't collide with the null coalescing operator nor with common sense – | is binary OR (or type union in TypeScript), : always separates name from value (or from type in TypeScript). Your new proposals don't seem lead anywhere nor do they solve any problem and .( is a thing I guarantee you'll get used to.