Skip to content

[SUGGESTION] eliminate operator precedence (and require parens) #622

@nigeltao

Description

@nigeltao

Is 3 << 5 - 1 parsed as (3 << 5) - 1 or 3 << (5 - 1)? C++ and Go give different answers!

#include <iostream>

int main() {  // Prints 48, which is "3 << (5 - 1)".
  int x = 3 << 5 - 1;
  std::cout << x << std::endl;
  return 0;
}
package main

import "fmt"

func main() {  // Prints 95, which is "(3 << 5) - 1".
	x := 3 << 5 - 1
	fmt.Println(x)
}

Similarly, 6 & 2 == 2 is 6 & (2 == 2) in C++ but (6 & 2) == 2 in Go. These reduce to 6 & 1 for C++ and 2 == 2 for Go, which are obviously different (0 and true).

For reference: C++ Operator Precedence and Go Operator Precedence

Like any curly-bracket language, Go looks a lot like C++, but copy/pasting a Go snippet from stackoverflow.com into a C++ program might have subtly different semantics.


I acknowledge that the SUGGESTION template says:

Please do not suggest syntax changes. I accept there are hundreds of opinions and everyone will prefer something a little different.

However, it also says "Please limit suggestions to quantifiable improvements to C++ simplicity, safety, or toolability" and there is a safety angle here. Operator precedence ambiguity has been a source of bugs in parsers. For example, in a library that emphasizes safety: jbangert/nail#7

Simplifying (by eliminating the idea of and need for precedence) is also similar to simplifying C++'s const T* type syntax. In C++, is it (const T)* or const (T*)? In cppfront, * const T is unambiguous, reading left-to-right.


The concrete suggestion: mandate parentheses when combining multiple binary operators. The programmer has to explicitly write either (3 << 5) - 1 or 3 << (5 - 1). A bare 3 << 5 - 1 would be a compiler error.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions