The Freya Programming Language

User defined operators

See also

Freya allows the use of symbolic operators as the name in user defined operations on new classes and records.

Operator overloading

User defined operators must be declared with their class or record, as public and static routines:

Vector = record
public
    constructor(X, Y, Z: Double);
    property X, Y, Z: Double;
    // ...

public
    // Vector addition.
    static operator+(V1, V2: Vector): Vector;
    // Vector addition.
    static operator-(V1, V2: Vector): Vector;
    // Scalar product.
    static operator*(V1, V2: Vector): Double;
end;

Since all user defined operators must necesarily be static members, you can drop the static modifier, and the compiler will assume its presence.

You must provide an implementation for these new operations in the implementation section of the declaring class or record:

implementation for Vector is

    constructor(X, Y, Z: Double);
    begin
        Self.X := X; Self.Y := Y; Self.Z := Z;
    end;

    operator+(V1, V2: Vector): Vector;
    begin
        Result := new Vector(V1.X + V2.X, V1.Y + V2.Y, V1.Z + V2.Z);
    end;

    operator-(V1, V2: Vector): Vector;
    begin
        Result := new Vector(V1.X - V2.X, V1.Y - V2.Y, V1.Z - V2.Z);
    end;

    operator*(V1, V2: Vector): Double;
    begin
        Result := V1.X * V2.X + V1.Y * V2.Y + V1.Z * V2.Z;
    end;

When redefining a symbolic operator, you can substitute the operator keyword by method:

Vector = record
    // ...
public
    static method+(V1, V2: Vector): Vector;
    static method-(V1, V2: Vector): Vector;
    static method*(V1, V2: Vector): Double;
    // ...
end;

Again, there's no need to include the static prefix.

User defined conversions

You can define new type conversions, both explicit and implicit, for your types. Explicit conversions are implemented by defining an operator named Explicit:

operator Explicit(V: Vector): Double;
begin
    Result := Math.Sqrt(X * X + Y * Y + Z * Z);
end;

Please note that you could also write a regular method called Explicit. In that case, however, the compiler will issue a warning. User defined implicit conversions are very similar, except they must use the Implicit identifier:

operator Implicit(D: Double): Complex;
begin
    Result := new Complex(D, 0.0);
end;

Though the compiler cannot verify this, implicit conversions must be written only when the conversion does not destroy information. Otherwise, an explicit conversion is recommended.

Expression-based implementations

As with properties and methods, operators can benefit from expression-based implementations, as this example shows:

    operator+(V1, V2: Vector): Vector =>
        new Vector(V1.X + V2.X, V1.Y + V2.Y, V1.Z + V2.Z);

    operator Implicit(D: Double): Complex =>
        new Complex(D, 0.0);

Since all user defined operators must have a return value, the only additional requirement is the operator's body must have only one statement, and it should be an assignment to Result. When transforming into a expression-based implementation, the begin/end pair is dropped, the left side of the assignment is also deleted, and the semicolon following the return type declaration is removed.

See also

The Freya Programming Language
Type declarations
Type members
Constructors
Methods
Iterators
Fields
Properties
Indexers
Events