-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
require parentheses sometimes to disambiguate confusing operator precedence #114
Comments
Interesting idea. This is on the table since it adheres to the principle that being readable is more important than being writable. Arguments against it are that it would be strange and cumbersome for people coming from a C background. People are used to |
👍 |
Some precedence is necessary, such as assignment, function call invocation, array index. Too much parens and the language turns into lisp. |
Assignment, function call, array index are not infix operators. Could there be any ambiguity with them? I can imagine having default precedence for basic arithmetic (+-/*), this is what little kids get drilled in schools, but IMO it is not worth the effort. One never writes |
Also, this feature would make adding user defined operators into the language easier. |
I think this would be a cool idea for some categories of operators, specifically the ones i can never remember the precedence for. e.g. |
see also #29 |
My favorite quote from the Pony page is
I love the idea for specific parens. It makes the execution crystal clear. |
The current operator precedence table is inspired by C. But I think Zig can do better than that. For example, I wanted to write up a proposal here to outline a new precedence table for operators in Zig, but Zig's grammar is a bit more complicated than the current table in At the very least, I'd like to see required parentheses for: |
Here's the real story on Zig's expression grammar (this does not include grammars such as statements, case declarations, top level declarations, etc.). I'll write a follow up comment documenting what i think the expression grammar should be changed to. There are three types of operator:
A chainable operator is one that you can use like The following is a list of operator groups. The groups are listed here in order of highest-to-lowest precedence. Each item in a group has equal precedence. If a group is chainable, the operators in the group can be intermixed while chaining (e.g. primary expressions:
prefix, not chainable:
suffix, chainable:
prefix, chainable:
suffix, not chainable:
infix, chainable:
infix, chainable:
infix, chainable:
infix, chainable:
infix, chainable:
infix, chainable:
infix, not chainable:
infix, chainable:
infix, chainable:
infix, chainable:
infix, not chainable:
prefix, chainable:
[1]: for the statement-like expressions |
For what it's worth I just removed the |
Here's my proposal for the "operator precedence table". It's a lot more complicated than a table. Before people automatically reject this grammar for being overly complicated, the goal here is to make Zig source code less complicated. My goal for grouping everything the way I did was so that any time a user would ask "Which of these two operators has precedence over the other.", the answer is that they're incompatible, and you need to use parentheses. Now clearly it's difficult to predict when users will ask that, and so most of the proposal is what I think is a good idea to me, and it's wildly up for debate and discussion. For example, why did I make modulo not heterogeneously chainable with multiplication? Because it seemed like you wouldn't really need that, and it would be more clear with parentheses I guess. It's pretty subjective, so debate on all points of the proposal is welcome and requested, even if you're just giving your opinion. What follows is a proposal (that has a lot in common with the existing situation), then a summary of changes from the existing grammar, and then some examples. ProposalThere are three types of operator:
The tree below has ordered lists and unordered lists. The ordered lists specify a precedence relation in order of highest to lowest (1 is the highest precedence.). An unordered list specifies a group of items that cannot be intermixed with each other, unless the header for the list specifies otherwise. Chainability comes in three forms:
[1]: for the statement-like expressions Proposed Changes
Examples
Here's some code that already follows this proposal from
Here's some code from
But this code from
Here's a curious case from
Perhaps that last case is a clue that we should not consider I want
But now that I think about that some more, it might not actually be correct. Consider if |
I agree with this proposal. Regarding the question at the end, let's just make it not chainable. Regarding |
can you give a usecase for chaining |
I meant that you would be able to do |
I'll take a look at this before 0.2.0. If anyone wants to see this in 0.1.0 feel free to make a pull request. |
Having I wouldn't mind contributing it once I've gotten my head around the current formatting code and zig in general. |
Based on I reckon there are 3 steps to this :
|
I think removing infix precedence would make things unambiguous, but also harder to read. By that I mean: the order in which things happen in would be clear, but would also slow down reading considerably. The human mind prefers infix, because infix is how natural languages (English, French, ...) are structured. To illustrate:
A more complicated example:
With the prefix and postfix notation, I can't even visually make sure the number of operators is correct. Not only is it hard to write, but also hard to read. However, I do agree that the entire precedence table is difficult to remember and I find myself either looking it up or adding extra parentheses anyway to make things clear. Thus, one radical way to solve this might be to entirely get rid of operator precedence for all binary operators (operators that take in two operands). For example, the following two lines would be equivalent:
Simply read from left to right. It's still somewhat awkward because of math classes hammering in the idea that multiplication happens before addition, but I think it's a reasonable compromise between readability and unambiguity. At the very least, I prefer this over the prefix / postfix notation. However, getting rid of the entire precedence table and going left to right would lead to the following: // consider this:
x += 3 * 5
// it converts to
(x += 3) * 5
// to get original meaning we would need to do this
x += (3 * 5) It's somewhat arguable if this really helps or not. Imagine reading through a 3-d math function full of this:
I feel like this might be more readable, but I can see somebody disliking it. TLDR:
|
A perhaps minor thing, but I feel like division should need parenthesis. 20 / 2 / 2, is it 1 or 5? Maybe I should be 100% certain after programming for 20 years but... I'm not. |
I think it's fair enough to assume basic mathematical knowledge, with division and multiplication first, left-to-right, and then addition and subtraction, also left-to-right. So |
Look at the cryptic table:
Why it is all needed? Who will find the time to learn it? I had not internalized C precedence after two decades.
Language Pony does it differently:
The text was updated successfully, but these errors were encountered: