Operator Overloading?

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

Should a given language allow operator overloading?

Always!
14
38%
Usually!
12
32%
Only under certain circumstances...
9
24%
Rarely!
0
No votes
Never!
2
5%
 
Total votes: 37

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Operator Overloading?

Postby sourmìlk » Sun Aug 05, 2012 5:04 am UTC

Admittedly this might be a religious wars thing, I'm not sure. But, what do you think of operator overloading? Is it useful, is that counteracted by the some disadvantage, should it be included in languages, which ones, etc.?

My take:

I like it. It's very convenient (particularly when writing math classes like Matrix and Vector and Complex and such), and it makes it really intuitive to use such classes. I've heard arguments that it can be misleading, but I'm not sure I buy that. For example:

Code: Select all

vec3 operator + (vec3 a, vec3 b)
{
    return vec3(a.x - b.x, a.y - b.y, a.z - b.y);
}


Isn't any more misleading than

Code: Select all

vec3 Add (vec3 a, vec3 b)
{
    return vec3(a.x - b.x, a.y - b.y, a.z - b.z);
}


So, it seems that operator overloading just exposes some useful and intuitive function names. The creators of Google Go make an interesting argument against including it:

Go FAQ wrote:[Operator overloading] seems more a convenience than an absolute requirement. Again, things are simpler without it.


And I'm not quite sure I get that argument. Just because it's not necessary doesn't mean it isn't useful, and if it's useful, I don't see why it shouldn't be included. I got into an argument with my dad about this and he says that he doesn't necessarily disagree with me, but I'm not really considering the other side's argument (which is so preposterous I'm not even going to consider that). So what do you all think? Is operator overloading ever appropriate? Why and when?
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

User avatar
Xeio
Friends, Faidites, Countrymen
Posts: 5101
Joined: Wed Jul 25, 2007 11:12 am UTC
Location: C:\Users\Xeio\
Contact:

Re: Operator Overloading?

Postby Xeio » Sun Aug 05, 2012 7:19 am UTC

I think operator overloading is nice, in that it can simplify code. It often looks much cleaner to to use an operator, especially for things like indexers. I think the equivalent Set(i, value) and Get(i) methods are ugly, but maybe that's me. :mrgreen:

That said, for most overloading it's not explicitly necessary, it's really just a prettier way to call a method. I don't think by itself it would be a deal breaker for a language for me.

Actually, I'm more weirded out that Go doesn't allow method overloads or optional parameters.

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Operator Overloading?

Postby sourmìlk » Sun Aug 05, 2012 8:13 am UTC

Xeio wrote:I think operator overloading is nice, in that it can simplify code. It often looks much cleaner to to use an operator, especially for things like indexers. I think the equivalent Set(i, value) and Get(i) methods are ugly, but maybe that's me. :mrgreen:


I agree about operator overloading, but generally not with properties. The problem with C#-style properties is that they obscure whether you're doing a function call or simply referring to a variable, meaning that you could be doing an O(n!) operation without realizing you're even calling a function. That's not the worst thing in the world, particularly when you know the language has properties, but I kind of don't like it.

Xeio wrote:Actually, I'm more weirded out that Go doesn't allow method overloads or optional parameters.

I know, I think they're way too worried about simplification. We already have C (now with threading in the standard library). I might see an argument for not overloading methods by types (after all, it might not be clear on reading a code which method you're calling if you don't immediately see the types of variables being passed as arguments), but I really don't see why you wouldn't be able to overload methods by number of arguments.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

Pixyn25
Posts: 10
Joined: Thu Feb 02, 2012 6:47 am UTC

Re: Operator Overloading?

Postby Pixyn25 » Sun Aug 05, 2012 9:11 am UTC

Sometimes, it can be useful to do operator overloading.

As an example, a hypothetical language allows overriding the operators that control indexing, comparison, function calls and so on.
Something like the code a[5]=(a[2]+3) could be translated internally into the method call

Code: Select all

    a:__put__(5, a:__get__(2)+3)

which could be useful if a's __put__ and __get__ methods are overridden to do stuff like database access.

Something like x<y (where x, y are objects/tables/whatever) could be translated to

Code: Select all

    x:__cmp__(y) < 0


Of course, since you now have no way to tell what will happen when you take something from an array, you could find yourself suddenly having a modal dialog box pop up when all you wanted to do was to, say, compare two objects; or you could face an inexplicable slowdown in indexing only to find that the object you have is actually a database connection to halfway across the planet.

Code: Select all

town.addChangeListener(new ChangeListener(){
   public void stateChanged(ChangeEvent e){
      if(e instanceof NewPersonInTown) throw new WelcomeParty();
   }
}

Take off your shipping goggles and put on the friendshipping goggles instead.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Operator Overloading?

Postby EvanED » Sun Aug 05, 2012 3:54 pm UTC

Pixyn25 wrote:Of course, since you now have no way to tell what will happen when you take something from an array, you could find yourself suddenly having a modal dialog box pop up when all you wanted to do was to, say, compare two objects; or you could face an inexplicable slowdown in indexing only to find that the object you have is actually a database connection to halfway across the planet.

To be honest, I've always thought this was a pretty BS argument. How would you index into a collection without operator overloading? Something like c.get(7). But .get has the same problem -- it could take foreever or make a database connection or whatever.

Operator overloading's biggest problem I think is how seductive it is to abuse for things where it doesn't really help readability.

User avatar
Sc4Freak
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

Re: Operator Overloading?

Postby Sc4Freak » Sun Aug 05, 2012 6:08 pm UTC

It's not so much that operator overloading increases the propensity for slow code when you don't expect it. It's that, without operator overloading, you can make stronger guarantees about what code does when looked at in isolation. If you see c[7] and you don't have operator overloading, you know exactly what that does. You know it's going to be fast, that it doesn't allocate memory, and that it doesn't connect to a database or do anything slow. It's only when you see a function call that you can say, "this expression may go off and so something slow and complicated".

For languages like C which are used in writing kernels, this is desirable. For everything else... I'll take the convenience of operator overloading any day. But the rule you should follow is that overloaded operators should behave "as you expect" without needing any extra knowledge. In other words, "when in doubt, do as the ints do". Subscript operators for collections are okay, as are addition and subtraction operators for custom numerical data types. But I've seen people overload operator* and operator| for vector cross products and dot products - I think that's awful style. Use functions for those sorts of things instead of changing the meaning of "*" and "|" for your custom type.

Great Justice
Posts: 54
Joined: Sun Aug 15, 2010 5:28 am UTC

Re: Operator Overloading?

Postby Great Justice » Sun Aug 05, 2012 9:29 pm UTC

I think it's a necessity for bottom-up development. The system shouldn't treat your UDTs as some foreign, 3rd-rate constructs and its own as special.
It usually isn't Congress or the State that tries to abridge free expression or free speech, [...] actually, in the present situation, the main threat to expression comes from public opinion.
~Christopher Hitchens

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Operator Overloading?

Postby troyp » Sun Aug 05, 2012 11:56 pm UTC

I like syntactic extension. In some cases that includes operator overloading. I certainly wouldn't say all languages should have it - I mean, some languages don't even have *operators*. And if you do have operators, operator overloading still seems a bit ad hoc. I'd prefer a more principled approach, like Haskell's type classes (unless that's meant to be included under "operator overloading"). But if it's operator overloading or nothing, I'd certainly prefer it, personally.

I think it's true that operator overloading (probably any overloading, I guess) makes a language more complicated and code more "non-local". In some cases, that might justify excluding it, if the language designer is willing to accept more verbose code in exchange.

sourmìlk wrote:So, it seems that operator overloading just exposes some useful and intuitive function names. The creators of Google Go make an interesting argument against including it:

Go FAQ wrote:[Operator overloading] seems more a convenience than an absolute requirement. Again, things are simpler without it.


And I'm not quite sure I get that argument. Just because it's not necessary doesn't mean it isn't useful, and if it's useful, I don't see why it shouldn't be included. I got into an argument with my dad about this and he says that he doesn't necessarily disagree with me, but I'm not really considering the other side's argument (which is so preposterous I'm not even going to consider that).

Are you saying the suggestion you should consider the other side is preposterous? Or that the other side in this case is preposterous on the face of it, so you're not going to consider it further?
Either way, I think that if smart people have an argument against your position, you should at least give it careful thought.

sourmilk wrote:The problem with C#-style properties is that they obscure whether you're doing a function call or simply referring to a variable, meaning that you could be doing an O(n!) operation without realizing you're even calling a function. That's not the worst thing in the world, particularly when you know the language has properties, but I kind of don't like it.

You realize this is the same sort of argument that can be made against operator overloading? I'm not saying it's inconsistent to call operator overloading one way and properties another, but I think the fact that you're taking the opposite position on an analogous issue should suggest that the question of operator overloading is not as black and white as you think it is.

EvanED wrote:To be honest, I've always thought this was a pretty BS argument. How would you index into a collection without operator overloading? Something like c.get(7). But .get has the same problem -- it could take foreever or make a database connection or whatever.

You could still index built-in types with []. I think the point of the argument is that using operator overloading makes it look like indexing will have similar properties to that for built-in collections (which may not be the case), whereas some other method name would be less misleading. I tend to agree with Sc4Freak that the onus should be on the user of overloading to not break expectations.

Great Justice wrote:I think it's a necessity for bottom-up development. The system shouldn't treat your UDTs as some foreign, 3rd-rate constructs and its own as special.

I agree, but I think operator overloading is little more than a token effort in that direction. You should be able to define your *own* operators (preferably with arity, precedence and associativity).

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Operator Overloading?

Postby sourmìlk » Mon Aug 06, 2012 2:25 am UTC

troyp wrote:Are you saying the suggestion you should consider the other side is preposterous? Or that the other side in this case is preposterous on the face of it, so you're not going to consider it further?
Either way, I think that if smart people have an argument against your position, you should at least give it careful thought.

I was joking.

You realize this is the same sort of argument that can be made against operator overloading? I'm not saying it's inconsistent to call operator overloading one way and properties another, but I think the fact that you're taking the opposite position on an analogous issue should suggest that the question of operator overloading is not as black and white as you think it is.

Not really. With an operator you know you're calling a function. That's ambiguous with properties.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

Ben-oni
Posts: 278
Joined: Mon Sep 26, 2011 4:56 am UTC

Re: Operator Overloading?

Postby Ben-oni » Mon Aug 06, 2012 3:04 am UTC

sourmìlk wrote:
You realize this is the same sort of argument that can be made against operator overloading? I'm not saying it's inconsistent to call operator overloading one way and properties another, but I think the fact that you're taking the opposite position on an analogous issue should suggest that the question of operator overloading is not as black and white as you think it is.

Not really. With an operator you know you're calling a function. That's ambiguous with properties.

Are you calling array access a function? Or adding two integers? They're not. C++ style overloading is exactly as obfuscating as properties.

I would say operator overloading is just as evil as function overloading. The problem, of course, is that before an operator or function is overloaded, there should be certain guarantees for the family. For instance, addition should be associative.

I really like how Haskell deals with the issue, where operators explicitly are functions, and function overloading is handled by typeclasses. This makes a lot of sense to me, and while it doesn't build in the guarantees (which I'm not sure could be enforced anyways), at least overloaders know to satisfy the conditions of the typeclass before doing so, and you know you're not going to get funky IO in the middle of an array indexing (unless someone used unsafePerformIO, then it's been made explicit, hasn't it?).

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Operator Overloading?

Postby sourmìlk » Mon Aug 06, 2012 3:10 am UTC

Ben-oni wrote:
sourmìlk wrote:
You realize this is the same sort of argument that can be made against operator overloading? I'm not saying it's inconsistent to call operator overloading one way and properties another, but I think the fact that you're taking the opposite position on an analogous issue should suggest that the question of operator overloading is not as black and white as you think it is.

Not really. With an operator you know you're calling a function. That's ambiguous with properties.

Are you calling array access a function? Or adding two integers? They're not. C++ style overloading is exactly as obfuscating as properties.

I fail to see how your two rhetorical questions support your conclusion.

Ben-oni wrote:I would say operator overloading is just as evil as function overloading. The problem, of course, is that before an operator or function is overloaded, there should be certain guarantees for the family. For instance, addition should be associative.

Why? Operators change properties even in normal mathematics (e.g. quaternion and matrix multiplication).

I really like how Haskell deals with the issue, where operators explicitly are functions, and function overloading is handled by typeclasses. This makes a lot of sense to me, and while it doesn't build in the guarantees (which I'm not sure could be enforced anyways), at least overloaders know to satisfy the conditions of the typeclass before doing so, and you know you're not going to get funky IO in the middle of an array indexing (unless someone used unsafePerformIO, then it's been made explicit, hasn't it?).

I've been reading Learn You a Haskell for Great Good! and I see why you like Haskell. It's a nicely designed language, and isn't as haphazard as, for example, C++. Not to say that it's necessarily better than C++ (I think that's an apples to oranges comparison), but it is pretty cool.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

Ben-oni
Posts: 278
Joined: Mon Sep 26, 2011 4:56 am UTC

Re: Operator Overloading?

Postby Ben-oni » Mon Aug 06, 2012 5:03 am UTC

sourmìlk wrote:
Ben-oni wrote:I would say operator overloading is just as evil as function overloading. The problem, of course, is that before an operator or function is overloaded, there should be certain guarantees for the family. For instance, addition should be associative.

Why? Operators change properties even in normal mathematics (e.g. quaternion and matrix multiplication).

No, the properties don't change, the operator changes. Multiplication in a ring is a different operation than in an algebra. There is some confusion in mathematics where symbols are reused, and we only know which is which based upon context, but such treatment tends to be someone informal, and are only accepted formally when the specific meanings are given in context. In programming, which is a highly formal environment, we do the same thing by explicitly defining scope and namespaces.

For instance, there are at least three ways to multiply 3-vectors. You could use an inner product, usually the dot product, or you could use the cross product, or you could do element-wise multiplication. Without context, "*" means nothing. In such a case, overloading should require a context. Either import the proper namespace, or relegate "*" to refer to multiplication in a ring (the Num typeclass in Haskell).

The important thing is that a function of a certain name should have a particular semantic meaning which is invariant with respect to overloading.

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Operator Overloading?

Postby sourmìlk » Mon Aug 06, 2012 5:18 am UTC

Cross product, dot product, and per-element multiplication use different symbols, don't they?

Also, why is it true that function semantics shouldn't change when overloading operators, but it's okay with functions? Or should it be true of both normal functions and operators, but it's difficult to enforce with normal functions?
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Operator Overloading?

Postby Jplus » Mon Aug 06, 2012 10:43 am UTC

In C++, overloading is available for types and the number of arguments. Nearly all built-in operators can be (re)defined for any type, if at least one operand is of user-defined type.

In Python there is no overloading, but many built-in operators can be implemented for user-defined classes using special member functions.

Lua has similar properties to Python in this regard, but the implementation of operators for a record is done through properties of its metatable, not by setting member functions to the object itself. The options are more limited than in Python.

In Haskell, overloading is available for types and patterns. Function names must either match [a-z][a-zA-Z0-9_']* or contain only "special characters" (such as $%:+). In the latter case, the function automatically behaves like an infix operator. Prefix and infix notations can be interchanged with syntactic sugar.

Forth has no distinction between functions and operators since everything is in RPN, and any printing non-whitespace character is allowed in a name. Names cannot be overloaded but they can always be overridden.

I believe that all these approaches make sense. It's because in each case the approach matches other aspects of the language, especially the typing system.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Operator Overloading?

Postby sourmìlk » Mon Aug 06, 2012 11:56 am UTC

You can overload the $ operator in Haskell? Wow, I like operator overloading and even I'm not sure about that. I mean, I guess it's no weirder than overloading () in C++, but something feels weird about it.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

Ben-oni
Posts: 278
Joined: Mon Sep 26, 2011 4:56 am UTC

Re: Operator Overloading?

Postby Ben-oni » Mon Aug 06, 2012 1:05 pm UTC

sourmilk wrote:Cross product, dot product, and per-element multiplication use different symbols, don't they?

Sure, but where are you going to find those symbols on the keyboard? "*" tends to fill in for each of them, depending on context.

sourmìlk wrote:You can overload the $ operator in Haskell? Wow, I like operator overloading and even I'm not sure about that. I mean, I guess it's no weirder than overloading () in C++, but something feels weird about it.

No, you can't. You can redefine it at the namespace level (and make it a part of a typeclass), but otherwise ($) is defined in the Prelude.

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Operator Overloading?

Postby sourmìlk » Mon Aug 06, 2012 6:07 pm UTC

Ben-oni wrote:
sourmilk wrote:Cross product, dot product, and per-element multiplication use different symbols, don't they?

Sure, but where are you going to find those symbols on the keyboard? "*" tends to fill in for each of them, depending on context.

Well you just overload the one that is available on the keyboard and use normal old function names for the others.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Operator Overloading?

Postby EvanED » Mon Aug 06, 2012 7:08 pm UTC

sourmìlk wrote:
Ben-oni wrote:
sourmilk wrote:Cross product, dot product, and per-element multiplication use different symbols, don't they?

Sure, but where are you going to find those symbols on the keyboard? "*" tends to fill in for each of them, depending on context.

Well you just overload the one that is available on the keyboard and use normal old function names for the others.

This is the sort of thing that leads people to dislike operator overloading, because it obscures the meaning. If you do what you suggest, and I see a * b, even if I know those are vectors, which one was it?

If there's ambiguity in what an operator does, it shouldn't be overloaded. (Some degree of exceptions allowed if you can define your own operators, or of course count Haskell-style a `op` b as an "operator.")

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Operator Overloading?

Postby sourmìlk » Mon Aug 06, 2012 9:44 pm UTC

Well the same can be said of function names, i.e. that you shouldn't overload them unless the meaning of each overload is clear.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Operator Overloading?

Postby EvanED » Mon Aug 06, 2012 10:13 pm UTC

sourmìlk wrote:Well the same can be said of function names, i.e. that you shouldn't overload them unless the meaning of each overload is clear.

Of course. The point is that times would be a pretty bad name for a vector multiplication too. I'm just saying that you shouldn't overload * in that case (just like you shouldn't use times), not that the fact that * is a bad name for the function means that operator overloading is bad.

User avatar
Steax
SecondTalon's Goon Squad
Posts: 3038
Joined: Sat Jan 12, 2008 12:18 pm UTC

Re: Operator Overloading?

Postby Steax » Tue Aug 07, 2012 1:29 am UTC

I'm curious. Does anyone have any benchmarks on how slow operator overloading is?

I've recently developed a dislike for all these nifty developer-benefit tools are, especially on interpreted languages. In PHP, my main playing field, everything from magic methods to type hinting to developer "sanity checks" can easily put strain on the code. It makes much more sense to have a debug mode that does strictly do all this, and then have a production mode that skips it.

So how does it fare on a compiled language? Is the effect negligible?
In Minecraft, I use the username Rirez.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Operator Overloading?

Postby EvanED » Tue Aug 07, 2012 2:10 am UTC

Steax wrote:So how does it fare on a compiled language? Is the effect negligible?

In C++ or Haskell, operator overloading has the overhead of a function call, which you'd need to have anyway. (And like function calls, that overhead can often go away if it's nonvirtual and there's a definition available at optimization time.) There's no overhead for primitive operations like 1+2.

This is true even in a language like Python for things like the arithmetic operations, but if you view things like __getattribute__ as being overloaded operators (it's sort of an overloaded . operator) then there's some overhead relative to raw field access. (Then again, in a language like Python, raw field access is "slow" anyway. :-))

User avatar
TheAmazingRando
Posts: 2308
Joined: Thu Jan 03, 2008 9:58 am UTC
Location: San Diego, CA

Re: Operator Overloading?

Postby TheAmazingRando » Tue Aug 07, 2012 5:47 pm UTC

I think overloading is nice, but only when there's only one way any reasonable person would expect it to work. If there's any ambiguity, or it isn't immediately obvious, you should use a function instead. Operators are only one or two characters, their function should reflect that simplicity.

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Operator Overloading?

Postby Jplus » Tue Aug 07, 2012 5:49 pm UTC

I second EvanED. To put the emphasis a bit differently: in C++ and Haskell, overloading/defining an operator adds no overhead compared to defining a function. In fact it's just a function with a special name and invocation. On top of that, it may be inlined just like any other function.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Operator Overloading?

Postby troyp » Wed Aug 08, 2012 12:09 am UTC

Jplus wrote:I second EvanED. To put the emphasis a bit differently: in C++ and Haskell, overloading/defining an operator adds no overhead compared to defining a function. In fact it's just a function with a special name and invocation. On top of that, it may be inlined just like any other function.

I'm not sure if that's true in Haskell in the case of *defining* an operator. User-defined operators in Haskell have custom precedence and associativity - I don't know how that works, but it's presumably going to involve some part of the parsing being deferred until runtime. At the very least, it's going to need some sort of table constructed when the program starts and an extra lookup to check precedence/associativity.

I think. (I don't really understand compilers.)

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Operator Overloading?

Postby sourmìlk » Wed Aug 08, 2012 12:19 am UTC

I'm surprised how close the community consensus about operator overloading is here. Nobody selected the Rarely! or Never! options as of posting.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Operator Overloading?

Postby EvanED » Wed Aug 08, 2012 1:16 am UTC

troyp wrote:
Jplus wrote:I second EvanED. To put the emphasis a bit differently: in C++ and Haskell, overloading/defining an operator adds no overhead compared to defining a function. In fact it's just a function with a special name and invocation. On top of that, it may be inlined just like any other function.

I'm not sure if that's true in Haskell in the case of *defining* an operator. User-defined operators in Haskell have custom precedence and associativity - I don't know how that works, but it's presumably going to involve some part of the parsing being deferred until runtime. At the very least, it's going to need some sort of table constructed when the program starts and an extra lookup to check precedence/associativity.

I think. (I don't really understand compilers.)

Nope. (Assuming you can't modify the precedence & associativity at runtime. :-))

It affects the efficiency of the compiler, but it does that lookup during compile time; it's a bit more complicated for the compiler writer than, say, the fixed associativity & precedence of + vs * in C, but there's no reason for any overhead.

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Operator Overloading?

Postby troyp » Wed Aug 08, 2012 1:32 am UTC

EvanED wrote:Nope. (Assuming you can't modify the precedence & associativity at runtime. :-))

It affects the efficiency of the compiler, but it does that lookup during compile time; it's a bit more complicated for the compiler writer than, say, the fixed associativity & precedence of + vs * in C, but there's no reason for any overhead.

Interesting. I found that quite counterintuitive for a moment, but it makes sense now. I was implicitly assuming the identity of an operator was determined at runtime, but of course that's nonsense. The only way you can pass an operator to a function is by turning it into a function itself and losing its precedence/associativity properties. So it could all be done at compile time.

User avatar
Grimgar
Posts: 12
Joined: Fri Jun 24, 2011 6:04 pm UTC

Re: Operator Overloading?

Postby Grimgar » Sat Aug 11, 2012 3:01 pm UTC

Despite the original title, discussion in this thread seem to cover three slightly distinct topics : operator overriding, user-defined operators and operator overloading.

Operator overriding is, in my opinion, a must have. Sure, you can go around it by using named function that do the same job and overriding those. But having to write (and to read) 'a.compareTo(b) < 0' instead of 'a < b' really feels terrible.

User-defined operators are... Nice? Potentially confusing? Unless I'm doing advanced mathematics, I can't figure why I would want (let alone need) to have user-defined operators. It is also much harder to parse, both for computers and for humans. If infix:<-++> is defined, should 'a -++ b' be parsed as '-++(a, b)' or as '-(a, ++(b))' ? Should this definition be allowed in the first place?

Operator overloading can be very useful, under certain conditions. In particular, I expect infix:<+> to be associative no matter what. An expectation that Java thouroughly crushed, while at the same time disallowing me to overload operators myself:

Code: Select all

System.out.println(1 + ('1' + "1")); // prints "111"
System.out.println((1 + '1') + "1"); // prints "501"

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Operator Overloading?

Postby EvanED » Mon Aug 13, 2012 2:10 am UTC

I don't understand how you distinguish between operator overriding and overloading... can you give an example of having each one without the other? (Especially overriding without overloading.)

KnightExemplar
Posts: 5494
Joined: Sun Dec 26, 2010 1:58 pm UTC

Re: Operator Overloading?

Postby KnightExemplar » Mon Aug 13, 2012 4:11 am UTC

EvanED wrote:I don't understand how you distinguish between operator overriding and overloading... can you give an example of having each one without the other? (Especially overriding without overloading.)


Scheme.

scheme@(guile-user)> (define (+ a b) (- a b))
scheme@(guile-user)> (+ 1 2)
$1 = -1


No overloading, you just overrided the + operator. Don't ask why you want to do this... but its possible. What a funny (and awesome) language.

EDIT: I guess it isn't overriding really. But if you did:

(define old+ +)

(define (+ a b)
(cond ((number? a) (old+ a b))
(else a))
)
scheme@(guile-user)> (+ 1 2)
$1 = 3
scheme@(guile-user)> (+ "hello" "world")
$2 = "hello"


Now the + operator is defined for non-numbers, while numbers have the old definition. I'm fairly certain that the object-oriented erm... library... to scheme can do something more akin to real overriding.
First Strike +1/+1 and Indestructible.

User avatar
Grimgar
Posts: 12
Joined: Fri Jun 24, 2011 6:04 pm UTC

Re: Operator Overloading?

Postby Grimgar » Mon Aug 13, 2012 3:58 pm UTC

EvanED wrote:I don't understand how you distinguish between operator overriding and overloading... can you give an example of having each one without the other? (Especially overriding without overloading.)

If you don't know the difference between overriding and overloading, please google it.
Here's an example of operator overriding without operator overloading, in Java pseudo-code :

Code: Select all

public class Point {
    public int x;
    public int y;

    @Override public boolean infix:<==>(Object o) {
        // Check equality by value rather than by reference
        return o instanceof Point &&
                ((Point) o).x == this.x &&
                ((Point) o).y == this.y;
    }
}

In "real" Java code, one can achieve similar (although less sugary) functionnality by overriding Object#equals(Object) instead.

As for an example of overloading without overriding... Well, that's the actual behaviour of infix:<+> in Java. I was already complaining about it in my previous post.

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Operator Overloading?

Postby Jplus » Mon Aug 13, 2012 7:30 pm UTC

The difference between overriding and overloading is actually quite simple, and once you know the difference it's obvious you can't have both at the same time.

Overriding: an existing function is given a new definition, the old definition is lost.

Overloading: an existing function is given an additional definition, which henceforth coexists with the old definition, so a call to the function gets different interpretations depending on the context.

(Note: in Grimgar's example, the == operator has already been overloaded as it applies to many more types than just Point. The code that is shown however only overrides the default implementation for Point and doesn't add to the multitude of other interpretations.)

As an aside: you can also define new functions, or delete existing functions (in some languages). I wonder whether that summarises the full statespace of possible actions on functions?
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

User avatar
Grimgar
Posts: 12
Joined: Fri Jun 24, 2011 6:04 pm UTC

Re: Operator Overloading?

Postby Grimgar » Tue Aug 14, 2012 11:59 am UTC

Jplus wrote:The difference between overriding and overloading is actually quite simple, and once you know the difference it's obvious you can't have both at the same time.

Overriding: an existing function is given a new definition, the old definition is lost.

Overloading: an existing function is given an additional definition, which henceforth coexists with the old definition, so a call to the function gets different interpretations depending on the context.

(Note: in Grimgar's example, the == operator has already been overloaded as it applies to many more types than just Point. The code that is shown however only overrides the default implementation for Point and doesn't add to the multitude of other interpretations.)

As an aside: you can also define new functions, or delete existing functions (in some languages). I wonder whether that summarises the full statespace of possible actions on functions?

I'll have to disagree with you:
- You can have both overriding and overloading at the same time
- When overriding a function, the old definition is not lost.

This little snippet of (working and tested) Java code proves both points:

Code: Select all

class A {
    int f(A a) {
        return 1;
    }
    int f(B b) {
        return 2;
    }
    static class B extends A {
        @Override int f(A a) {
            return 3;
        }
        @Override int f(B b) {
            return 4;
        }
    }
 
    public static void main (String... args) {
        A a = new A();
        B b = new B();
        System.out.println(a.f(a)); // 1
        System.out.println(a.f(b)); // 2
        System.out.println(b.f(a)); // 3
        System.out.println(b.f(b)); // 4
    }
}


Overriding does not mean replacing the definition of a method. It means providing a more specific implementation of a method defined in a superclass. Which definition to call is determined at runtime, based on the runtime type of the object (which may be any concrete class that extends/implements its compile-time type).

User avatar
Sizik
Posts: 1243
Joined: Wed Aug 27, 2008 3:48 am UTC

Re: Operator Overloading?

Postby Sizik » Tue Aug 14, 2012 1:02 pm UTC

Grimgar wrote:- When overriding a function, the old definition is not lost.


It's lost in the sense that you don't get 1 when you call

Code: Select all

b.f(a);
since the new definition replaces the old one for B. Although, it depends on whether you can do something like

Code: Select all

((A)b).f(a);
and get 1 rather than 3.
gmalivuk wrote:
King Author wrote:If space (rather, distance) is an illusion, it'd be possible for one meta-me to experience both body's sensory inputs.
Yes. And if wishes were horses, wishing wells would fill up very quickly with drowned horses.

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Operator Overloading?

Postby Jplus » Tue Aug 14, 2012 1:48 pm UTC

@Grimgar: you have a point. When you redefine an inherited method for a subclass, it appears very much like overriding and overloading at the same time. However, strictly speaking the function is first overloaded (as it may be called on a new class) and then the new interpretation is immediately lost because it's overridden with another new interpretation, as Sizik pointed out. The fact that you're overloading the method for different argument types as well doesn't change anything about the situation.

Keep in mind that this apparent combination of overloading and overriding only applies to class inheritance with member functions, while both overriding and overloading can apply (independently) in a multitude of other contexts.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Operator Overloading?

Postby troyp » Wed Aug 15, 2012 3:18 am UTC

I don't know the details of Java, but in general overriding is orthogonal to overloading. Operator overloading is a form of ad hoc polymorphism. Overriding is redefining something - usually redefining something within a limited scope, eg a subclass (in this case it may also be a type of ad hoc polymorphism, eg inheritance polymorphism). There's no reason you can't have both at once. In a simple example, an operator may be overloaded in class Foo and Foo subclass Bar may override that overloaded definition. In this case, you could claim the overriding is in some sense "irrelevant" to Bar's overloading of the operator, but it still exists. Bar's definition is at once overloading the operator and overriding the definition from its parent.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 9 guests