Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow operator overloading and cast methods in classes #2803

Closed
Herschel opened this issue Mar 24, 2014 · 18 comments
Closed

Allow operator overloading and cast methods in classes #2803

Herschel opened this issue Mar 24, 2014 · 18 comments
Assignees
Milestone

Comments

@Herschel
Copy link
Contributor

I have seen several people on haxelang or IRC ask about operator overloading. They have some Vector2D that they want to add operators to, but then they read about abstracts and get confused. It's not trivial for a new user to create a separate wrapped type, write forwarding methods/properties, and juggle the abstract vs. underlying type. Why should this be necessary just to support addition on a vector?

It seems to me that wrapping an underlying type is orthogonal to operator overloading or casts. I don't see any reason why @:op, @:from, and @:to could not be allowed on classes, as well. Allowing operator methods directly on the class would simplify the common case of vectors and matrices.

This would be a big change in the compiler, so this is a longer-term issue for discussion.

@ncannasse ncannasse added this to the Long term milestone Mar 24, 2014
@ncannasse
Copy link
Member

I think that would be pretty hard to implement. Not the @:op themselves but the @:from/@:to. I would prefer that we keep it for abstract only at least until Haxe 4 (or even 5).

@Simn
Copy link
Member

Simn commented Mar 24, 2014

Instead of implementing operator overloading directly on classes I would prefer if you could import operator overloading to a file. This would work similar to normal static extensions with @:op methods being brought into context through using.

The two main advantages are that this can be done without modifying the class code and that you can find all operator overloads by looking at the import/using declarations.

@waneck
Copy link
Member

waneck commented Mar 24, 2014

I think that we could easily leave @:from/@:to out for classes - as they really have much more sense for Abstracts only - but still support @:op .

@porfirioribeiro
Copy link
Contributor

I also agree with having @:op on classes.
I think @:to could also be supported for casting, as Haxe already do with toString
@:from makes no sense in a class, i would rather perfer to have a @:op(=) as in c++
No changing the type itself but being able to set an underlining value.

For example @aduros Flambe Value type https://aduros.com/flambe/api/flambe/util/Value.html could benefit from this.
Being able to do: mySprite.x=10 instead of mySprite.x._=10

@Simn
Copy link
Member

Simn commented Mar 24, 2014

I won't implement implicit casts or operator overloading on anything that allows inheritance.

@Herschel
Copy link
Contributor Author

@Simn, the static extensions idea is interesting. It also solves the annoying question of which file defines the operator. Do I put Vector * Matrix in Vector or Matrix? Neither, now I put it in MathUtils.

@Herschel
Copy link
Contributor Author

Herschel commented Mar 25, 2014

Just as an example of how class operator overloading might look:

class Vector2 {

  public var x : Float;
  public var y : Float;

  public function new( x : Float = 0, y : Float = 0 ) {
    this.x = x; this.y = y;
  }

  @:op(A+B) public static function add( a : Vector2, b : Vector2 ) : Vector2
    return new Vector2( a.x + b.x, a.y + b.y );
}

This would be the same if ops were implemented via static extensions, too -- it would require the user to add using Vector2 to their module.

BTW, I'm not concerned so much with implicit casts. I think they are mostly bad style anyway. I just figured they were under the same umbrella of "doesn't need to be an abstract".

@deltaluca
Copy link
Contributor

I always thought, and agreed with the fact, that we don't have operator overloading/cast overloading for non-abstract types, is because that apart from almost none of our targets supporting such things, such things are not amenable to dynamic resolution. Aka if we had operator overloading on classes, we'd need to compile 'any' operator between Dynamic/untyped and something else as a huge case of checking what the type is, whether it has an overload for that operator etc, which is all currently done at compile time for abstract types.

@ncannasse
Copy link
Member

@deltaluca Yes that's one of the reasons. In general I prefer to keep runtime behavior quite near from compile time one. Properties and Abstracts are two exceptions, the first one because it's very useful and there's not always runtime support, the second because it's good for performances and allow to perform core-type emulation (Int32, UInt, Vector, etc.)

@Simn
Copy link
Member

Simn commented Mar 25, 2014

That's another good reason to work with static extensions because they already rely on things being typed correctly, so there would be no additional restriction.

@frabbit
Copy link
Member

frabbit commented Mar 25, 2014

if we move ops from classes to "impl"-classes we can do the same for static inline functions on extern classes.

@frabbit
Copy link
Member

frabbit commented Mar 25, 2014

hopefully we can also support ops and functions for enums this way, like how you can do it currently with @:enum abstracts.

@back2dos
Copy link
Member

Any news on this? Operator overloading by means of static extensions sounds like a sound idea.

@Simn
Copy link
Member

Simn commented Mar 19, 2015

I don't think this is a good time to ask about long term issues.

@back2dos
Copy link
Member

Ok, sorry, never mind then. I just ran into a situation where this would be very helpful. Also, I thought I could take advantage of the calm before the storm that'll ensue once rc.1 ships officially ;)

@Simn
Copy link
Member

Simn commented Dec 1, 2015

This approach might cause regressions in cases abstracts are used via static extensions. I had to fix some parts of Int64 because it was using itself as static extension, which lead to operations like Int - Int being resolved to one of its @:op(A - B) methods.

This is not enough for me to dismiss the entire approach, but I'll have to think about it a bit more.

@nadako
Copy link
Member

nadako commented Dec 30, 2015

Now when we have #1138 implemented, this thing is actually very useful IMO!

@ncannasse
Copy link
Member

This will have to go through Haxe Evolution process, although I'm still against it given it's covered by abstracts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants