ecmascript-operator-overloading-proposal icon indicating copy to clipboard operation
ecmascript-operator-overloading-proposal copied to clipboard

Should operator overload methods be instance methods instead?

Open JorisBlanken opened this issue 7 years ago • 3 comments

Currently the proposal states that the methods that provide the operator behavior should be static. I understand that this is the convention in other languages that implement operator overloading such as C#, however I don't think it's applicable to weakly typed javascript.

Consider the following code:

class Example {

    static [Symbol.operator('+')](left, right){
        return ... ;
    }

}

let x = 5;
let y = new Example();
let z = x + y; // What does this do?

As demonstrated, there is a lack of clarity as to what this should result in, in this case I would assume that it would preform addition using default behavior, e.g. returning a string. However this might not be what we want to happen.

In languages such a C#, operator overloading with different types is done by using method overloading, another feature JS does not have. I propose that the following be considered for this proposal: use operator symbols as instance methods instead, where this is always the left hand operand for binary expressions, and this is the operand in unary expressions. This way the following can be achieved:

class Example {

    constructor(value){
        this.value = value;
    }

    [Symbol.operator('+')](right){
        if(right instanceof Example){
            return new Example(this.value + right.value);
        }
        else if(right instanceof Number){
            return new Example(this.value + right);
        }
    }

}

This also conforms to current Symbol standards such as Symbol.toPrimitive and Symbol.iterator. I am aware that Symbol.hasInstance uses a static method, however this is applicable as the instanceof operator involves a class type as it's operand.

I also understand that this leaves a gap, namely that in this case, using a non Example instance as the left hand operand will result in the operator overloaded type not being called.

I am strongly in favour of this proposal and I think that this should be discussed.

JorisBlanken avatar Sep 21 '18 20:09 JorisBlanken

I have to agree that having operator overloading as instance methods was my first thought (ie: only having right as a parameter). I believe this will only depend on the implementation on a lower level.

If we end up adding operator overloading as static methods, it could be called only if both operands are instances of the given class, and if one of them is not, would call valueOf() to get the primitive value. if I'm not wrong this would be based directly on how JavaScript works today:

Consider: (you can run it on your console and check the validity)

class Example {
    constructor(value) {
         this.value = value;
    }

    valueOf() {
    	return this.value;
    }
}

let example = new Example(5);

console.assert(example + 5 === 10);

Although I agree having a one operand operator overload function would allow developers to more flexibly get the results they are looking for it would change the fundamentals of how operations are run in the language in my opinion, which is why I would personally prefer a 2 operand static approach.

jsmrcaga avatar Feb 05 '19 14:02 jsmrcaga