-
Notifications
You must be signed in to change notification settings - Fork 23
?? has poor associativity/precedence, leading to counterintuitive behavior #26
Comments
In other words, in a chain like that, with no parens, I'd assume |
@waldemarhorwat The precedence of @ljharb What gives you that intuition? |
I see all three of these operators as value-selection operators, and see the short-circuiting behavior as just something that falls out of that. |
@ljharb Are you aware that |
Somewhere in the back of my mind :-) but I use linting rules to force parens when && and || are mixed. So perhaps it'd be clearer to not talk about && at all - I'm still not clear on the reason why |
Yeah, giving |
@waldemarhorwat would that mean that |
If (edited, as the last patch had some big typo in it) |
This was raised in #15, which some good points in it. |
Thanks @waldemarhorwat. We should follow C# here and give |
If I remember correctly, C#'s There are some other practical concerns I think are worth considering. I was going to suggest that the And I was going to suggest that it's more important we make sure that However, I am wrong about the likelyhood of if (opts.somebool ?? true || someSituationThatForcesThisPartOfTheLibraryToRunUnconditionally ) {
// Do something that can be disabled sometimes by passing {somebool: false} to the options
} I also want to double check that the result of i.e. I can see libraries writing code like this: const someoption = opts.someoption ?? defaults.someoption ?? 0;` Read as "someoption is equal to someoption from the options passed in to the function, but if not defined falls back to the library wide default values the user specified, but if that library wide default was not supplied by the user is |
I still feel |
Adding as much cross-language data here as I can find:
|
@rkirsling What #38 mean for this issue? Will we change the precedence? |
@hax I'm not the PR author, but hopefully @DanielRosenwasser's latest reply over there helps. 😄 From my personal perspective, I really believe that C# et al. are doing the right thing. const isValid = options.isValid ?? hasValidFoo() && hasValidBar(); ...and I would hope that it would work equally well if the condition were based on |
I agree with @rkirsling in that if there are no restrictions, I will bring up lowering the precedence at the next meeting to gauge whether there is strong opposition to doing so, but based on feedback from the last meeting, and in the interest of progress on the feature, adding an early error appears to be the best way forward. |
Thank you @DanielRosenwasser and @rkirsling for explaining! And I really appreciate the #39 instead of #38 which also rule out About the code example const isValid = options.alreadyValidated ?? hasValidFoo() && hasValidBar(); The name |
@rkirsling It seems coffeescript is same as C#. ( |
Personally I kind of like Swift way, or strictly speaking, even more aggressive than Swift, I expect the precedence of Let me explain the idea: All binary expressions from So in real engineering, we need to introduce a linter rule to disallow To summary the idea of Pros:
Cons:
|
Derp, guess I tried to get too clever with the name and made it imply the wrong thing. What's there is correct if It's difficult to think of a real-world example for
Whoa, you're right! I was looking at the unary postfix |
i'm currently against imagine reviewing/debugging integration-code, and you stumble across the logic
the code's intent is likely option 1. option 2 is pathological/bad-programming, in terms of data-handling. |
Already stage 4, this issue could be closed. |
When faced with a long short-circuiting expression such as
I usually think of it as selecting the first one of
a
,b
,c
,d
,e
that's not falsy and not evaluating the rest. In effect, I'm viewing the expression as though it were right-associative:That works fine. The spec grammar happens to actually specify it as left-associative:
However, that associativity is merely a spec-writing artifact, invisible to users. The spec could have associated the other way without any visible changes to existing user code behavior.
Unfortunately, introducing
??
at the same precedence level as||
makes the spec associativity visible in the language and leads to problematic consequences:Intuitively, if
??
and||
have the same precedence level, I'd expect this to short-circuit starting at the0
and produce the result0
. However, as specified, this will produce7
instead.There are three possible solutions:
??
its own precedence level??
with||
without parenthesizing oneThe text was updated successfully, but these errors were encountered: