HaloO,
I've mentioned the concept of supertyping in several posts
but now I want to dedicate a thread to it because it increases
the expressive power of Perl 6 if one can form abstractions
not only by creating subclasses and subroles but also by going
in the other direction. Here are some use cases where this is
useful:
Set <: Bag
Set <: FuzzySet
Num <: Complex <: Quaternion <: Octonion
Vector <: Matrix <: Tensor
Square <: Rectangle
The subtypes should be considered as given and the supertypes as
derived. Some code follows that explains how that might be done
for the Num <: Complex case. The key idea is that the ComplexRole
provides a default implementation of the .im accessor for Num.
role NumRole does Order
{
multi infix:<+> ( Num $a, Num $b) {...}
multi infix:<*> ( Num $a, Num $b) {...}
method abs {...}
...
}
class Num does NumRole {...}
role ComplexRole superdoes Num # handwave, note that Complex doesn't
# do Order which is fine for a supertype
{
method re { return self as Num } # noop for Num
method im { return 0 }
method abs {...}
method arg { return self.re < 0 ?? pi !! 0 }
multi infix:<+> ( Num $a, Num $b) {...}
multi infix:<*> ( Num $a, Num $b) {...}
...
}
class Complex does ComplexRole
{
# accessors overwrite role defaults
has Num $.re;
has Num $.im;
multi infix:<+> ( Complex $a, Complex $b)
{
return new Complex( $a.re + $b.re, $a.im + $b.im );
}
multi infix:<*> ( Complex $a, Complex $b)
{
return new Complex( $a.re * $b.re - $a.im * $b.im,
$a.re * $b.im + $a.im * $b.re );
}
method abs { return sqrt( self.re**2 + self.im**2 ); }
method arg
{
if self.im > 0 { return acos( self.re / self.abs ); }
elsif self.im < 0 { return 2*pi - acos( self.re / self.abs ); }
elsif self.re < 0 { return pi; }
else { return 0; }
}
...
}
This works as far as the Complex numbers are defined in terms of the
.re and .im methods but fails as soon as you want them to be Complex
constructors in lvalue context:
use Complex;
my $x = 3.2;
$x.im = 1.2; # becomes a non-real complex
$x.arg = pi/4; # same
The question here is how the class Complex can receive the dispatch on
the Num class for putting a new Complex into $x. This is BTW yet another
example of changing an objects type while preserving its identity---see
the thread 'how to change the type of objects'. I mean here we have
value semantics anyway but in general a superclass might want to
preserve object identity while changing the type.
So will we have supertyping in Perl 6? If yes, how would my superdoes
be spelled? Same applies to a superis for classes.
Regards, TSa.
--