Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Any language feature has the potential to be abused to create cryptic code.


Sure, the effect of operator overloading is no different than that of using undescriptive names. Except with operator overloading, the name is almost guaranteed to be undescriptive.


I must disagree strongly. With operator overloading, the name is guaranteed to be highly descriptive. Think about all that's implied by something as simple as + or /. They might seem superficially undescriptive, but they carry a lot of context due to the huge amounts of history these symbols have.

The problem with operator overloading isn't a lack of descriptiveness, but using them for things they don't describe. If you overload / to perform network IO or something, the problem isn't that / is an undescriptive name, the problem is that it means "numeric division". It's no different than if you wrote a function called "divide" that did network IO.


'+' or '-' doesn't adequately describe operations even in the numeric domain (e.g. overflow conditions). They are recognizable only because almost every language has similar semantics for integer or floating point arithmetic. But even using '+' for something like string concatenation unmoors it from historical context.

And beyond that, you're just making things up. '<<' for input/output?

We spent thousands of years developing the written word just so we wouldn't have to rely on primitive pictographs to vaguely get our points across.


That "only because" is my entire point. It's like, aside from the whole reason symbols are useful, they're not useful.

If you've been paying attention, I hold up << for IO as an excellent example of operator overloading gone wrong. But it's not because << is undescriptive, it's because << means "bit shift".


Your justification of "huge amounts of history" only applies in very limited contexts, all of which can be hard wired without allowing general operator overloading.

"<<" does not mean "bit shit." Several languages use it to mean "bit shift," but many do not, and even in those languages the usage is ambiguous. C uses two operators that, visually, could refer to six different operations: arithmetic shift left/right, logical shift left/right, rotate left/right (on x86: shr, shl, sar, sal = shl ror, rol). As a result, the C standard leaves right-shifts of signed negative numbers implementation defined.


How can those limited contexts be hardwired without allowing general overloading? What if I want to write a new numeric type?

Seems like you're just talking about operators, not overloading. If << doesn't have a distinct meaning then it shouldn't be used. If it's OK to use << it should be OK to use it both for built-in types and custom types.


I'd argue that << was a bit of a misfeature anyways. Providing operators for mathematical symbols with well-known meaning is sensible. == is an understandable hack, but a hack, nonetheless. || and && probably could have just used the words AND and OR like SQL does.

The << operator was just using symbols for the sake of symbols and would have been much more semantically clear with Shift(value, nBits) and would've avoided temptation to overload this meaningless operation.


You have a good point. I don't know if I completely agree, but I can see the merit in it. However, you're now talking about the merits of operators in general, rather than overloading, which is a different thing altogether.


The issue is that operators rarely have obvious semantics when applied to non-builtin types. '+' makes sense for integers and floating point numbers, complex numbers and ratios, and almost nothing else. Those types can be built into the language, and '+' defined on them. It doesn't make any sense for strings and all the mismash of things people will overload it for.


I've never seen anybody confused by "+" for string-concatenation. It makes far more sense than, say, integer division where 5/3 = 1.

Just because C++ ruined operator overriding with their moronic << doesn't mean that every other language should live without perfectly reasonable operator behavior. I've been dealing with Java instead of C# and not being able to use simple obvious equality checks with the "==" operator is agonizing.


Languages should build in all the numeric types you could ever need, but they don't. A lot of languages still don't have arbitrary-size integers (Swift among them).

You see the vast majority of cases not needing operator overloading and see it as useless, while I see the small number of cases where it's really, really good and see it as important.


To reductio ad absurdum, we shouldn't even include arithmetic operators for numerical types because of ambiguities regarding truncating decimal places. After all, myInt1 / myInt2 is dangerously undescriptive so really all integer division should use

Math.DivideToFloat(myInt1, myInt1) or Math.DivideToInteger(myInt1, myInt2)


Language design has to balance expressiveness with maintainability, and there is absolutely no question that some additions lean far more to the former than the latter.

Operator overloading, as mentioned, is something that seems fantastic when you're banging out a bunch of code. When you return to that code a month later, however, with no context, it leads to mystery code with completely undefined behavior without tracing back through every constituent. We constantly see people make the (unsupported) claim that scientific coding simply needs operator overloading, and while I can't speak specifically to that industry, in the financial industry operator overloading is how you end up with terrible, mystery-meat code.


I think a language should either have operators, or it should not.

There's a decent case for not having operators at all. Lisp being a fine example of this. Everything is a function, end of story.

But once you have operators, what's the rationale for restricting them to built-in types? This, to me, fundamentally makes no more sense than, say, banning user-created types altogether.

Clearly nothing needs operator overloading, but if you have operators at all, why should "a + b" be valid if and only if a and b are certain language primitives? If you think + should only be used for numeric addition, I'd totally agree, but numeric types don't have to be restricted to built-in ones.


I can certainly understand how that sentiment arose back in the dark ages of early operator-overloading abuse.

I'm starting to wonder, however, whether the horror stories are continuing to propagate long after anyone has seen a real, living monster.

If I'm browsing someone else's code today in a modern development environment and I encounter a function I don't know it's generally pretty easy to navigate to the definition (if it's in the codebase) or documentation (if it's not).

If operator overloading is just a function with a name that happens to be a string of symbols and with infix application at the call site, can't I find out about it just as easily?

What's the difference between

   myMysteryFunction(a,b)
and

   a + b
…if I know that the type of a and b isn't something ordinary like an int or a float?


Well, for me, the latter would masquerade as a trivial expression seen thousands of times, and which now may or may not have unexpected behavior. Every instance of something like a + b must now carry the slight extra cognitive load of potentially having a sort of "optional type annotation" in one's mind. Usually normal, but might not be.

The former is at least potentially self-documenting. And even if it's a badly named function, at least you know it's a special function, and you know you'll have to go look up its behavior.

[Edit: Clarity]


Done right, it should masquerade as a trivial expression seen thousands of times. There's a real advantage in being able to have user-defined types that have the same interface as native types.

I want the ability to do 'a == b' regardless of whether it's a built-in or user-defined type. That's abstraction.


That's a good point, and I agree. The situation I'm thinking of is something like, say, you have an object or type called a "Tire". It has width, diameter, weight, price, tread depth, compound, etc. As you work with Tires in your program, you frequently end up having to compare their widths. So you overload the ">" operator to return true if one Tire has greater width than another. Your code ends up festooned with these comparisons.

Flash forward one year, you're long gone, and new developers on your team are left wondering which aspect of a Tire is used in comparisons with ">". Everything works, but it's easy to see how the ambiguity could lead to subtle submarine bugs; incorrect developer assumptions about the behavior of ">" may produce mostly -- coincidentally -- working code.


I think I'd rather take that risk than have another scenario like BigInteger in Java:

http://stackoverflow.com/questions/1783912/java-how-to-use-b...


It's true that I can't provide evidence that scientific computing NEEDS operating overloading beyond my own anecdotal experience. However, I've also never seen any support that operator overloading muddies code, besides other people's anecdotal experience.

The simple example I always come back to is how hard it is to find the bug in the following code:

    divide(add(multiply(-1,b),multiply(-1,sqrt(add(multiply(b,b),multiply(multiply(-3,a),c))))),multiply(2,a))
versus finding the same bug operator overloaded version

    (-b-sqrt(b^2-3*a*c))/(2*a)


That's a good point, but those operators have really clearly-defined semantics, so they don't have the ambiguity issue.


I'll also concede that I've seen some try abominations with oeprator overloading. Would people be willing to compromise with just allowing the overloading of addition, subtraction, multiplication, and division?

I know that overloading << or || can lead to some confusing code, but offering the basic arithmetic operators would end 90% of the whining by the people who do scientific code and need this functionality.


Do you prefer the C library interface for working on strings to the way that Java handles them, then?

After all, Java allows statements like "string3 = string1 + string2;", which is much more ambiguous than C's "strcpy( string3, string1 ); strcat( string3, string2 );" (or a modern equivalent where those functions are namespaced in a string class).

I work on 3D games. Sometimes I work in languages (c++, c#, shader languages) that allow me to use operator overloading (and thus infix notation) for 3D vectors and matrices. And sometimes I work in languages (actionscript, java, javascript) that don't allow me to use operator overloading and infix notation for vector and matrix math.

The code in the latter set of languages is much, much, much less readable by nearly any reasonable measure.


Let me expand on what I think is the point of the GP:

I hate operator overloading myself, but at the same time I'm also certain there are use cases where it is a big win. (I assume it is in Swift because it could be motivated well.)

You'll have to specify coding standards anyway -- and make certain that they are followed. Just add a paragraph about having to get a senior developer's signature on any use of operator overloading, on pain of needing to update the CV.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: