Logo

Programming-Idioms

This language bar is your friend. Select your favorite languages!
  • Perl

Idiom #268 User-defined operator

Define a type vector containing three floating point numbers x, y, and z. Write a user-defined operator x that calculates the cross product of two vectors a and b.

use Object::Pad;
class Vector {
    has $x :accessor;
    has $y :accessor;
    has $z :accessor;

    BUILD { ($x, $y, $z) = @_ }

    use overload 'x' => sub { shift->xprod(shift) };

    method xprod ($v) {
        return Vector->new(
            $self->y * $v->z - $self->z * $v->y,
            $self->z * $v->x - $self->x * $v->z,
            $self->x * $v->y - $self->y * $v->x,
        );
    }
}

my $a = Vector->new(3, 4, 5);
my $b = Vector->new(5, 10, 1);
my $cross = $a x $b;

This is the modern perl way to do it, using an OO module such as Object::Pad.
package Vector {
    sub new {
        my ($class, $x, $y, $z) = @_;
        bless [$x,$y,$z], $class;
    }
    sub x { shift->[0] };
    sub y { shift->[1] };
    sub z { shift->[2] };
    
    use overload 'x' => sub { shift->xprod(shift) };

    sub xprod {
        my ($self,$v) = @_;
        return Vector->new(
            $self->y * $v->z - $self->z * $v->y,
            $self->z * $v->x - $self->x * $v->z,
            $self->x * $v->y - $self->y * $v->x,
        );
    }
}

Perl classic OO (i.e. not using module like Moose or Object::Pad) which defines a Vector class. See demo for more. Arguments are passed as a list; Operator shift removes the first item from the list, usually $self (or $class).
record Vector(double X, double Y, double Z)
{
    public static Vector operator *(Vector a, Vector b)
    {
        return new(
            a.Y*b.Z - a.Z*b.Y,
            a.Z*b.X - a.X*b.Z,
            a.X*b.Y - a.Y*b.X
        );
    }
}

C# allows operator overloading but not operators with user-defined names.

Because it is ambiguous whether the * operator between two vectors is dot product, cross product, or component-wise multiplication, each of these should be implemented as a static method instead.

Refer to the built-in 3D vector type, linked as 'Origin'

New implementation...
< >
tkoenig