Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why not just ? #3

Closed
bevacqua opened this issue Feb 5, 2016 · 14 comments
Closed

Why not just ? #3

bevacqua opened this issue Feb 5, 2016 · 14 comments

Comments

@bevacqua
Copy link

bevacqua commented Feb 5, 2016

Hey. I was wondering why not just use ? instead of ?..

The operator is spelt ?. and may be used at the following positions:

obj?.prop         // optional property access
obj?.[expr]       // ditto
func?.(...args)   // optional function or method call
new C?.(...args)  // optional constructor invocation

Versus:

obj?.prop         // optional property access
obj?[expr]       // ditto
func?(...args)   // optional function or method call
new C?(...args)  // optional constructor invocation

I find obj?.[expr] to be awkward

@nhz-io
Copy link

nhz-io commented Feb 5, 2016

it will confuse the parser (? :)

@bevacqua
Copy link
Author

bevacqua commented Feb 5, 2016

I don't foresee lots of people writing code like a ? a?[expr] : b

@nhz-io
Copy link

nhz-io commented Feb 5, 2016

what about:
a ? b?[expr] : c ?

@bevacqua
Copy link
Author

bevacqua commented Feb 5, 2016

It's a matter of precedence, just like a * b + c,

  • b?[expr]
  • a ? (above) : c

I can see how it can be confusing to somebody reading the code, though.

@bevacqua bevacqua closed this as completed Feb 5, 2016
@claudepache
Copy link
Owner

Above all, it would be very hard to write an efficient parser that distinguishes between:

a?[b]+c      // interpreted as:  (a?[b]) + c
a?[b]+c:d    // interpreted as:  a ? ([b] + c) : d

(And the interpretation of the second expression cannot be changed due to backward compatibility concerns.)

@Mouvedia
Copy link

Mouvedia commented Jul 15, 2017

@bevacqua this shouldn't have been closed that fast.
Is having an "efficient parser" trumping the overall readability/consistency?
This is unusual and not expected, hence not desirable.

I find obj?.[expr] to be awkward

I wholly agree. It also has been brought up in tc39/proposal-optional-chaining#5:

It seems strange to me…

@claudepache
Copy link
Owner

@Mouvedia

Is having an "efficient parser" trumping the overall readability/consistency?
This is unusual and not expected, hence not desirable.

In short, the only reasonable way I have found for a parser to disambiguate the two forms, is to try to parse one way, and, if an error occurs, trash all the work and try to parse the other way. From an implementer perspective, this is unusual and not desirable.

Also, from a user perspective, it means that a forgotten or mistyped : may radically change the meaning of the expression, which is not desirable either.

I am not going to fix this issue on my repo. Formally, that does not mean it won’t be fixed in the official proposal, but personally I strongly doubt it will.

@pronebird
Copy link

pronebird commented Jul 21, 2017

a?() exists in Swift and they have ternary operator too, somehow it works very well in C# as well.

a?.() looks very strange and the meaning is lost because we used to access properties with . operator. This ?. operator looks like we are accessing unnamed property in object.

This works in Swift very well (although I must admit this is really synthetic example):

let wat = (foo?.baz ?? false) ? "whoa" : "boo"

with rough equivalent in javascript:

let wat = (foo && foo.baz) ? "whoa" : "boo";

In fact Swift doen't allow optional chaining in ternary expressions because foo? is null then the result of .baz is also optional and they don't accept optional for such comparison, therefore null-coalescing false backup is needed to compile that piece.

Hard to implement sounds like a weak argument. Weird syntax does not benefit anyone. It's possible to throw error/warning and ask developer to add parenthesis or spaces around condition if transpiler cannot disambiguate the expression.

Speaking of backward compatibility case:

a?[b]+c:d

Basically we are talking about the use of array accessors [...] and function calls, everything else should be straightforward:

a?[b]+c:d; // warn developer, compile as (a) ? [b] + c : d;
a?(e)+c:d; // warn developer, compile as (a) ? (e) + c : d;
a?"str"+c:d; // (a) ? "str" + c : d;
a?new b()+c:d; // -> (a) ? new b() + c : d

What else am I missing here? I see only two ambiguous uses.

(a?[b])?c:d; // OK
(a?(e))?c:d; // OK

Besides the suggested expression (a?[b]+c:d) only looks ambiguous if you parse it left to right, otherwise if ternary operator and optional chaining had somewhat precedence when parsed then it's pretty clear that it's either syntax error because : has no ? counterpart or it's trivial (a) ? [b] + c : d

@claudepache
Copy link
Owner

@pronebird

What else am I missing here?

See above. If you are able to propose a solution to that issue that would convince the TC39 technical committee, please discuss it either on es-discuss or on the official repo (https://github.com/tc39/proposal-optional-chaining).

@ikokostya
Copy link

ikokostya commented Nov 7, 2017

@claudepache I read discussion, but don't see technical details.

#3 (comment)

Above all, it would be very hard to write an efficient parser that distinguishes between:
a?[b]+c // interpreted as: (a?[b]) + c
a?[b]+c:d // interpreted as: a ? ([b] + c) : d

Can you add explanation why do you think so?

@pronebird
Copy link

@ikokostya his comment mentions the case:

a?[b]+c:d // interpreted as: a ? ([b] + c) : d

No human can tell what's going on there and it's impossible to keep backward compatibility if constraints are introduced to disambiguate such cases.

@ikokostya
Copy link

@pronebird I don't understand you. Provided example

a?[b]+c:d // interpreted as: a ? ([b] + c) : d

always has deterministic result. What you mean under backward compatibility?

@pronebird
Copy link

pronebird commented Nov 8, 2017

@ikokostya it doesn't. ? could be a part of ternary expression or optional chaining in that example. It's hard to tell without parser looking ahead to get more clues, but even worse It can be programmer's error too. Given that JS is a dynamic language and there is very little typo information, there is no way to tell when transpiling into JS. Also JS can be written in one line without a single space so it makes it even harder, the grammar has to be consistent to allow for that. Backward compatibility means that any new addition to the language shouldn't break any existing features.

@js-choi
Copy link

js-choi commented Nov 11, 2017

It’s also worth pointing out here that JavaScript-parser efficiency is important in the performance of web pages in general, just like it is for the HTML and CSS parsers. JavaScript parsing often takes up a nontrivial amount of time in addition to download and execution. For many devices, this can sometimes add several hundred (or even several thousand) milliseconds on the critical rendering path.

For years, TC39 has been careful not to create time-costly syntactic disambiguation/backtracking at every ternary operator in every script. Any such performance regression may significantly increase the first-to-load times (and, of course, monetary losses) of many websites. This is not a luxury that the syntax of an assembly language for the web has, and it is frankly a miracle that TC39 has been able so far to increase its developer ergonomics this much under such tight constraints.

When optional chaining is added, its syntax will fulfill those same constraints. Such must be JavaScript’s forward compatibility.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants