-
Notifications
You must be signed in to change notification settings - Fork 23
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
Make assignment/arrow operators right associative, change precedence of -> #467
Comments
IMO right associativity is always unintuitive since we read text from left to right. And it's true for all the examples you bring up. I understand that We should look into removing more right associativity, not embrace it. |
If you asked me when I discovered Nim 5 years ago i would have say yes, it was one of my main issues and the often listed solution, to use a Now I'm not too sure due to potential breakage.
Devs read intuitively |
Good point but actually even that syntax is suboptimal. First This might also be the reason why people prefer to split up "deeply nested" expressions. -- Split up into what exactly? Into "statements". What is the difference between these two? Statements are actually run "in order". |
I've been looking up operator precedences from the manual since day 1 of using Nim (really any language). With this logic precedence is bad too because it's arbitrary past PEMDAS since kids memorize it from primary school. The difference is that the parser validates people writing There are actually many "implicit" operators that the parser does not treat as such but the human eye can be tricked into thinking it is. For example: let foo = proc (a: int): auto = proc (b: int): int = a + b Despite there being only 1 instance of an operator call in this code ( If that's not a good argument for associativity, then it should at least be a good argument for Sidenote:
This is also an operator taken from functional languages, |
I don't understand your way of arguing, the examples you bring up are indeed all questionable style that would be better off using And yes, exactly. The current rules are already a bit too complex for my taste and it feels like you're making them worse. But even if not and we would agree on these improving the situation objectively there is also the argument that it breaks backwards compatibility. And while you can argue reasonably that no code in reality will be affected in the past that is exactly what happened for other very comparable changes. However, you can implement your preferred solution in a PR and then we can see how many important packages would break. As a starting point. |
Abstract
Make the assignment and arrow like operators as described in the manual have right associativity. To make this work, also increase the precedence of
->
, making it no longer an "arrow operator".Motivation
Right associativity is pretty self explanatory. Left hand sides of assignment operators are meant to be addresses, not other assignment operator expressions. This is why in almost every language, assignment operators are right associative. But it's not that noticeable in Nim since most assignment operators are statements. For arrow operators,
a => b => c
evaluates to(a => b) => c
which is also meaningless, hence lambda operators are also right associative in most languages.Arrow operators, which the manual lists as having a lower precedence than assignment operators, have actually had equal precedence with assignment operators since their implementation, maybe as a mistake. This means expressions like
a => b += c
parse as(a => b) += c
which is also, meaningless. However, lowering arrow operators' precedence is not needed to alleviate this, making these operators right associative would do the same thing.Arrow operators were, however, originally right associative. This was changed in order to make
a -> b => c
parse as(a -> b) => c
. There is another alternative fix here: Increase the precedence of->
. It doesn't really make that much sense either, for->
, having simple type operands, to have the same precedence with=>
, which has a general statement operand on the right hand side.->
also being right associative is intuitive, sincea -> b -> c
meaninga -> (b -> c)
is a common pattern in functional languages and the left hand side usually has parentheses anyway due to multiple parameters.Description
->
in some other languages, aside from the function type meaning, occasionally can also mean "dictionary entry", "pairing", or "range" (sometimes=>
is this way and->
is like Nim's=>
). This generally has a higher precedence.The precedence for
->
should probably be above 1 (assignment). Beyond that, it's a matter of whether or not stuff likeint or float -> string
should mean(int or float) -> string
orint or (float -> string)
. I think 2 is best, it seems to be more semantically similar to those operators than the others to me.So far specifically
->
has been mentioned but it would be simplest to make all arrow operators starting with-
have the higher precedence. I haven't seen such operators used too often but I'm guessing they generally wouldn't lose from the precedence change. There is also the~>
variant but again, I haven't seen its uses.There is also the idea of arrows and assignments going left like
<=
and=+
which would have inverted associativity but this just adds another way to do the same thing.Not sure if there is any particular reason for assignments not being right-associative. I can see it just being due to simplicity of the associativity calculation since expression assignments are not too common. This is the biggest downside of the RFC, is the performance implications from the extra computations for associativity + separate checks for
->
arrows vs other arrows.Code Examples
Backwards Compatibility
Since there is basically no genuine use of the involved operators without this behavior, most code uses parentheses here, and isn't affected. Could be wrong. New code using it though will not work with older versions.
The text was updated successfully, but these errors were encountered: