Skip to content

Instantly share code, notes, and snippets.

@adamierymenko
Last active September 1, 2018 23:58
Show Gist options
  • Save adamierymenko/a03a62da1513a8cc2ac4dfac81b44a9f to your computer and use it in GitHub Desktop.
Save adamierymenko/a03a62da1513a8cc2ac4dfac81b44a9f to your computer and use it in GitHub Desktop.
Proposal for limited operator overloading in Go

After looking over some of the Go 2 generics proposals, I kept thinking about the primary utility of generics. For the most part it lies in collections, algorithms, and math code. For the latter however generics really don't help a whole lot without operator overloading. The versatility of C++ operator overloading combined with low or zero cost generics is what makes C++ really shine for reusable math libraries and number crunching.

However I also love love love Go's simple parsimonious nature. This is the most true thing I have ever read about programming. Some people see Go as a language for entry level programmers, but I disagree. I'm 40 and have been programming since I was between 5 and 8 years old (Commodore VIC-20 baby!) and I love it. To me it's a language for people who are past their fascination with overdone high cognitive load abstractions.

I don't want to see anything added to Go that damages that. Operator overloading misused -- meaning use outside areas where it really matters -- is one of the things that over-complicates C++ code.

So here's my idea:

Add operator overloading to Go, but make it only apply to generic/template variables.

If only generic templated variables can override operators, this limits operator overloading to only where it actually provides value and keeps it from polluting the rest of the language.

An alternative to this idea that is slightly more verbose but maybe better is to require explicit declaration of where operator overloading is to be applied. This would look something like this:

type Something struct {
  x int
}

// only works if explicitly enabled in a function
func (s *Something) Operator+=(s2 *Something) {
  s.x += s2.x
}

// only works if explicitly enabled in a function
func (s *Something) Operator+(s2 *Something) *Something {
  var tmp Something
  tmp.x = s.x + s2.x
  return &tmp
}

func(foo *Something, bar *Something) {
  var foo func operators {+=, +} // list of operators overloaded
  //type Something func operators {+=, +} // alternative version that does it to all Somethings
  //var foo func operators {...} // alternative that allows any/all operators to be overriden
  foo += bar // only works with the above line, otherwise the overloaded ops are ignored
}

This shows it being done in a regular function, but it would be most useful in generic functions. This again limits the "damage" of operator overloading misuse by requiring that it be explicitly lampshaded. That way when I am reading the code and I see this I know "+" in this function can be a function invocation and not just plus.

@adamierymenko
Copy link
Author

I must also add that this would make big.Int and big.Rat a lot nicer to work with. As it stands they're a bit painful.

@hooluupog
Copy link

hooluupog commented Sep 1, 2018

I really like the idea of operator method introduced by Robert Griesemer in dotGo 2016[0]. The math/Big package is a mess without supporting operator method and generics at present. IMO, Generics with proper operator method supporting will significantly enhance Go's ability in Data Science (Gonum will be the biggest beneficiary). In addition, a decent decimal(#issue 12127) library could be introduced into Go with this feature.
There are two flaws in java's generics implementation, type erasure and inconsistency. In java, the '+', '=', and '[]' operators only work for built-in types. When using generics type(user-defined type), i have to use named method for the operations('Add()',' Equal()', 'Array.set()', etc.) It's a pity that i can not use range with a generic container and i can only access it with just ordinary methods but not with syntax like c[k] in Go. The built-in generic types(slice, map) and user-defined generic types should not be treated differently(introducing the unnecessary complexity). We should avoid making the java mistakes again. Keep the language simple and clean.
[0]. dotGo 2016 - Robert Griesemer - Prototype your design!

@adamierymenko
Copy link
Author

I posted this over at the go2 generics feedback page too, but wanted to mirror it here.

I had another idea: a form of operators that is overloadable. In this idea a + b would be like today's Go and would not be overloadable, but a [+] b would be overloadable. The [operator] syntax means "use the built-in operator or an overload if available".

For indexes a[[b]] could be an overloadable [] operator.

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