Skip to content

Instantly share code, notes, and snippets.

@maj-o
Last active October 3, 2018 15:15
Show Gist options
  • Save maj-o/9cab355e3e5e4f6f66dbf0a8f24cd13a to your computer and use it in GitHub Desktop.
Save maj-o/9cab355e3e5e4f6f66dbf0a8f24cd13a to your computer and use it in GitHub Desktop.
Golang 2 operator methods

Problem

We do a lot of calculations on currency values - calculating income taxes, bills, ... As You all know, float in any kind, does not work. (for those, who don't know that there is a problem: There are problems with float-types and there are problems without decimal type(s) - for instance this: https://groups.google.com/forum/#!topic/golang-nuts/SfdApDgi4i8 ).

This is why there are so many implementations of a decimal type in different go packages. With all this packages and the build in types You can save Your decimal values to databases - one small step! But You can do nothing else. In Go there will be no serious calculations with decimals or any other not build in type. Because You have no operands for values of this types, You have to user Methods like Add, Mult and so on. This a No Go for uge calculations on (for instance) decimals.

What we do

We have realy a lot of currency calcualtions (each year new formulars for taxes and insurances) - there is no way using decimals for this, because it's actually not readable. So we use decimals in database and float64 for calculations, though knowing that the calculated results are wrong and we have to convert the values twice. On some places we use our own round functions, because checking if a value is greater than a border with float valuas is like throwing dice. So we have to much code, workarounds and hidden errors - but we have also readable code for komplex formulars - and this is important - it's convinient for reviews and changes.

What would be better

Thoughts

My first thought has been, that Go is missing decimals, like it has complex numbers. Maybe, but there are other calculations with other types - and it would be much easier, if each type could have its own Operator implementations. If the assignment operator would also be a method - this would be perfect.

Some people fear the misuse of operator methods. If this is the point: You as developer have the choice which package You use and how You implement something. If You don't like it, don't use it. I don't fear it, because it would just impact a type declared in the same package - so operator methods can not do harm.

There are so many workarounds on github trying to make decimals usable. I'd like to have the choice and use one decimal implementation where complex formulars are quickly readable and their results correct. For small calculations, like in an online shop system, it may be just convinience. For us it's realy importartant.

Target features to cover any type:

  • to be able to apply standard operators on any types, if this operators are defined
  • and to be able to define operators for any types

Example:

// operator method for decimal addition
 func (a decimal) + (b decimal) decimal {
  return a.Add(b)
}

possible usage:

var a decimal
var b decimal

...

c := a + b

That's it! Simple and sexy

The solution has been implemented and presented by Mr. Griesemer: https://www.youtube.com/watch?v=vLxX3yZmw5Q

Perfect for linear algebra, taxes, bills, and any other problem where operands make common sense.

Well, I am not a great (text) writer - I just want this topic not to be forgotten, if somebody thinks about Go 2

@puellanivis
Copy link

While I love the power available in being able to define operators for types upon which these operations make sense… all too often, these get used for “overly creatively“ solutions to problems that it should probably not be applied to.

The biggest example of this is perhaps the “cout” and “cin” and operator overloading given in the C++ stdlib. Arguably, the decoration is nice, but it fundamentally breaks away from the semantics of the operators which they use.

Linear algebra, and currencies and many mathematical types carry semantically analogous mathematical operators. But opening up operator redefinition opens up the ability to fundamentally break the semantics behind operators.

@umitanuki
Copy link

+1 for support of custom operators. While I do know there are tons of bad examples around operator overloading, I also do know that it's powerful and simplifies the code a lot when it's used correctly. I barely touch C++'s operator overloading since I know it goes bad easily. Scala's operator system was one of the reasons I jumped into Go immediately since it clearly said no operator overloading is better than way too much of freedom. I still think that's the case, but years since, I now know that python's ecoysystem around pydata, numpy etc. wouldn't have realized without custom operators (I also know there are several attempts to port numpy to Go, but I felt I would be using them for some reasons including lack of custom operators). Then now what I believe is that custom operators should be hard to define so that only people who know what they do should do it, and most importantly the symbols used for custom operators should be limited. I think +, -, *, /, <, > and == should be enough and as far as we allow only those custom operators, people won't get confused much (it's clear what each of them means, isn't it?) Allow it, but don't give much freedom.

@maj-o
Copy link
Author

maj-o commented Oct 3, 2018

Overloading may be bad, but this is not the target.

Methods are declared in the same file as the used struct.
Like this, it would be great to be able to declare operator-methods for this struct, in the same file.
No overloading elsewhere.

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