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

Support a very basic form of operator overloading #1520

Closed
marijnh opened this issue Jan 14, 2012 · 4 comments
Closed

Support a very basic form of operator overloading #1520

marijnh opened this issue Jan 14, 2012 · 4 comments

Comments

@marijnh
Copy link
Contributor

marijnh commented Jan 14, 2012

(RFC)

We could add interfaces core::num and core::deref, with the first implementing methods add, sub, mult, div, rem, neg, and probably a few more, and the second only deref. The compiler can then resolve operators +, -, *, /, %, and [x] on types that are not built-in numerics or vectors as if they were calls to the corresponding method (1 + 1 => 1.add(1)), and numeric-style and sequence-style user types can implement these interface to allow the operators to be applied to them.

This is not the most elegant solution (1 + 1 is more like add(1, 1) than 1.add(1)), but it would give us operator overloading on the short term, without first needing a lot of extra interface features.

We will need some kind of support for a 'self type' in interface declarations to be able to say that add takes an returns a value of the type that the interface was specialized on, which is not currently expressable.

@ghost ghost assigned marijnh Jan 14, 2012
@nikomatsakis
Copy link
Contributor

I am a big fan of this general idea. I think we should use generic types where it makes sense: in particular the deref interface should be something like fn get(k: K) -> V, so that it works with maps. But it makes sense even for operators like + and * if you plan to stretch their numeric meaning a bit:

inter mul<R, V> {
    fn mul(r: R) -> V;
}

would allow

impl of mul<int, str> for str {
    fn mul(times: int) -> str {
        let base = self;
        uint::range(1, times) {|| base += self; }
    }
}

you could then write " "*15, as you can in Python. The danger is that it opens the door to implicit numeric coercions, but at least users have to write those themselves rather than us doing it for them.

However, I think the fact that one must implement all core:num or none is not so appealing. I'd rather have the individual operators broken out into individual interfaces and then a core:num group interface. I can certainly think of things that are addable but not subtractable (strings and vectors) and so forth.

I guess it depends a bit on whether we intend for these operators to be used strictly for their analogous purposes or whether we intend to allow nicer notation for a few other cases. I say intend because people will use them for other things beyond numerics and lists whatever we do, but I guess we can make it more painful for them if we want to.

@marijnh
Copy link
Contributor Author

marijnh commented Jan 14, 2012

I can certainly think of things that are addable but not subtractable (strings and vectors) and so forth.

I guess this is a matter of taste. I like operators to mean one thing and only one thing -- I think Haskell's Num class gets it right. But since Rust is already abusing + for vector concatenation, I'm okay with supporting separate interfaces and allowing people to do more free-form things.

@kevina
Copy link
Contributor

kevina commented Jan 20, 2012

This issue sorta relates to Issue #535.

@kevina
Copy link
Contributor

kevina commented Jan 21, 2012

Actually I was reading the summary for 535 way too fast, it was about overloading in general and not operator overloading.

In any case, I believe that if Rust is going to support ad-hoc operator overloading, it should also allow defining new operators. Otherwise the existing operators will be abused to do things that have nothing to do with the original operator's meaning; for example the << operator in C++.

marijnh added a commit that referenced this issue Jan 26, 2012
When no built-in interpretation is found for one of the operators
mentioned below, the typechecker will try to turn it into a method
call with the name written next to it. For binary operators, the
method will be called on the LHS with the RHS as only parameter.

Binary:

    +   op_add
    -   op_sub
    *   op_mul
    /   op_div
    %   op_rem
    &   op_and
    |   op_or
    ^   op_xor
    <<  op_shift_left
    >>  op_shift_right
    >>> op_ashift_right

Unary:

    -   op_neg
    !   op_not

Overloading of the indexing ([]) operator isn't finished yet.

Issue #1520
marijnh added a commit that referenced this issue Jan 26, 2012
The method `op_index` (which takes a single argument) is used for
this.

Issue #1520
marijnh added a commit that referenced this issue Jan 27, 2012
It's less likely to clash with something than 'neg'.

Issue #1520
@marijnh marijnh removed their assignment Jun 16, 2014
celinval pushed a commit to celinval/rust-dev that referenced this issue Jun 4, 2024
Kobzol pushed a commit to Kobzol/rust that referenced this issue Dec 30, 2024
bors pushed a commit to rust-lang-ci/rust that referenced this issue Jan 2, 2025
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

3 participants