Git Product home page Git Product logo

operator-overloading's Introduction

Operator Overloading

In some situations operator overloading can result in code that's easier to write and easier to read.

without overloading

let u = new Vector(1, 0);
let v = new Vector(2, -1);

let w = u.add(v);
w = w.plus(v.scale(3));

with overloading

let u = new Vector(1, 0);
let v = new Vector(2, -1);

let w = u + v;
w += 3 * v;

Function.defineOperator

Binary operators are defined as follows:

Function.defineOperator(
    '+',
    [Vector, Vector],
    (u, v) => new Vector(u.x + v.x, u.y + v.y)
);

Unary operators are defined as follows:

Function.defineOperator(
    '-',
    [Vector],
    (v) => new Vector(-v.x, -v.y)
);

Notes:

  • Commutative operators, +, *, &&, ||, &, |, ^, automatically flip the order of operands when their types are different.

  • Function.defineOperator(T == T, (a, b) => fn(a, b) will automatically define != as (a, b) => !fn(a, b).

  • ! and != cannot be overloaded in order to perserve identities:

    X ? A : B <=> !X ? B : A
    !(X && Y) <=> !X || !Y
    !(X || Y) <=> !X && !Y
    X != Y    <=> !(X == Y)
    

    Source: http://www.slideshare.net/BrendanEich/js-resp (page 7)

  • > and >= are derived from < and <= as follows:

    A > B     <=> B < A
    A >= B    <=> B <= A
    

    Source: http://www.slideshare.net/BrendanEich/js-resp (page 8)

  • Redefining some operators on some built-in types is prohibited. The reason being that operator overloading should be used to make classes that don't have operator support easier to work with and prevent changing behavior of those classes do that.

    • all operators on [Number, Number]
    • logical operators on [Boolean, Boolean]
    • + on [String, String]
    • unary + and - on [Number]

'use overloading' directive

The 'use overloading' directive can be used to limit the scope of overloading can be used. This directive is opt-in because for existing code it will have negative performance impacts. In general, overloading should be used where readability is more important that performance.

It can be used at the start of a file or function/method definition. The @operator section has an example of the 'use overloading' directive in action.

@operator decorator

The @operator decorator is a convenience for declaring methods as operators when defining a class.

class Vector {
    constructor(x, y) {
        Object.assign(this, { x, y });
    }

    @operator('+')
    add(other) {
        return new Vector(this.x + other.x, this.y + other.y);
    }

    @operator('-')
    neg() {
        return new Vector(-this.x, -this.y);
    }

    @operator('-')
    sub(other) {
        'use overloading';
        return this + -other;
    }

    @operator('*', Number)
    scale(factor) {
        return new Vector(factor * this.x, factor * this.y);
    }
}

The @operator decorator makes the assumption that both operands are the same type as the class. If this is not the case, the type of the other operand can be specified as the second parameter to @operator.

Implementation Details

The following code:

'use overloading'

let u = new Vector(1, 0);
let v = new Vector(2, -1);

let w = u + v;
w += 3 * v;

relies one the following operators to be defined:

Function.defineOperator(Vector + Vector,
    (u, v) => new Vector(u.x + v.x, u.y + v.y);

Function.defineOperator(Number * Vector, (k, v))

and compiles to:

let u = new Vector(1, 0);
let v = new Vector(2, -1);

let w = Function[Symbol.plus](u, v);
w = Function[Symbol.plus](w, Function[Symbol.times](3, v));

The implementation defines the following well-known Symbols:

Binary Operators

  • Symbol.plus +
  • Symbol.minus -
  • Symbol.times *
  • Symbol.divide /
  • Symbol.remainder %
  • Symbol.equality ==
  • Symbol.inequality !=
  • Symbol.lessThan <
  • Symbol.lessThanOrEqual <=
  • Symbol.greaterThan >
  • Symbol.greaterThanOrEqual >=
  • Symbol.shiftLeft <<
  • Symbol.shiftRight >>
  • Symbol.unsignedShiftRight >>>
  • Symbol.bitwiseOr |
  • Symbol.bitwiseAnd &
  • Symbol.bitwiseXor ^
  • Symbol.logicalOr ||
  • Symbol.logicalAnd &&

Unary Operators

  • Symbol.unaryPlus +
  • Symbol.unaryMinus -
  • Symbol.bitwiseNot ~

Note: only the following operators can actually be overloaded: |, ^, &, ==, <, <=, <<, >>, >>>, +, -, *, /, %, ~, unary-, and unary+

Function Lookup

The functions for each operator are stored in a lookup table. When a call to Function.defineOperator is made, we get the prototype for the types of the arguments. The prototypes are stored in a protoypes array the index of the prototype from that array is used to determine the key in the lookup table.

In the case of unary operators the index is the key. For binary operators, the index is a string with the two indices separate by commas.

TODO: describe how prototype chain support works.

Future Work

  • handle prototype chain
  • support exponentiation operator
  • use static type information to improve performance (could determine which function to call at compile time)

operator-overloading's People

Contributors

kevinbarabash avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

operator-overloading's Issues

Why Function.defineOperator?

I like the idea of operator overloads, but what does it have to do with Function? Why is it a static method on Function? Why not global.defineOperator(), or a new Meta object with the method, or something?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.