develooper Front page | perl.perl6.language | Postings from February 2005

Re: How are types related to classes and roles?

Thread Previous | Thread Next
From:
Larry Wall
Date:
February 23, 2005 12:17
Subject:
Re: How are types related to classes and roles?
Message ID:
20050223201718.GA10967@wall.org
On Wed, Feb 23, 2005 at 06:21:02PM +0100, Thomas Sandlaß wrote:
: HaloO,
: 
: I'm very puzzled about what is meant by type and class in Perl6.
: In the sort ruling
: http://groups-beta.google.com/group/perl.perl6.language/msg/1eb1ed4608f5604d
: we saw a system of types that allow to nicely dispatch into different 
: version
: of &sort. OTOH every class or role name can serve the same purpose.
: Built-in value types like Str and Int seem to be auto-coercive instead of
: MMD, in particular when playing together with dedicated operators like
: binary '+' versus '~'.

One can view the auto-coercion as a form of MMD if you allow the
autogeneration of any necessary coercion methods.  However, it's not
exactly a coercion to Str or Int--it's more like promotion to a Scalar
that is able to pretend it is either Str or Int.  Or you can view it
as a kind of cached conversion.  The ~ operator doesn't demand the
Str type--it only demands something which can fulfill the string role.

: And how does all this combine with the notion of context?

Lazily, for the most part.  In some cases we can determine context at
compile time, but often not.  Certainly a subroutine cannot determine
what context it was called in until it's actually called, unless we
venture into return-value MMD, which has problems resolving against
parameter MMD.

: I guess that basically influences method selection.

Up to a point.  At some point we effectively have to mix in methods
if we want to have allomorphic types like Perl 5 scalars.

: Take the following example:
: 
: # part 1
: class Cyclic[uint $base] is Int
: {
:    multi *postfix:<++> ( Cyclic[uint $base] $i )
:       returns Cyclic[uint $base]
:    {
:         return (($i as uint) + 1) % $base;
:    }
:    multi *infix:<+> ( Cyclic[uint $base] $x, Int $y )
:       returns Cyclic[uint $base]
:       is symmetric
:    {
:         return abs( ($x as uint) + $y ) % $base;
:    }
:    ...
: }
: 
: # part 2
: sub foo( Int $begin, Int $end )
: {
:    while $begin < $end
:    {
:       ...
:       $begin++; # assumes Int axiom: $i + 1 > $i
:    }
: }
: 
: #part 3
: my Cyclic[8] $cyclic = 3;
: 
: foo( $cyclic, 10 ); # never returns?
: 
: 
: Does the design intent to catch such "surprises"?
: E.g. by giving an error at the line 'class Cyclic[uint $base] is Int'?

I don't see how.  I suspect there are gazillions of ways to violate Liskov
substitutability that are in the realm of the halting problem.

: But how should the violation of an abstract property of Int be checked
: by the compiler?

I don't think that's going to be Perl's job.  Where Perl 6 is going with
this it to give the programmer enough tools that they don't feel like they
have to use inheritance to do subtyping.  The whole point of a subtype is
to violate Liskov, so that's why it's a separate concept.

: Can this just be remedied by source code review and human reasoning?

"Yes" and "no" are both correct answers to such a question.

: Is there a chance for designers of classes like Int to prevent method
: overriding which violates some constraints?
: If yes, how are these constraints specified?

Sure, just use DBC to supply complete regression tests as PRE and
POST blocks.  Your program is not gonna run very fast though...

Oh, wait, maybe you want compile-time constraints.  Sorry, I'm no
good at those.  One could, I suppose, set up some kind of expert
system that will reason about code, and at least tell you when it
can and can't decide.  But usually we just call that sort of thing
compile-time strong-typing, and most current Perl programmers don't
like it very much.  They tend to be more into late-binding solutions.
It's possible to bridge that gap somewhat with type inferencing, but
I'm no expert in that either.

I think the best thing we can do here is to encourage a culture in
which people recognize the fundamental difference between extending
a base class and constraining a subtype, and learn to use composition
and delegation where appropriate instead of inheritance.  That's why
we've given different keywords to all those concepts.  It's a matter
of giving people the mental tools to think straighter.  It's another
one of those natty little psychological problems that partially prove
and partially disprove the Sapir-Whorf hypothesis, which is generally
true when you want it to be false, and false when you want it to be true.

: my Cyclic[7] enum DayOfWeek <Mon Tue Wed Thu Fri Sat Sun>;
: 
: Another thing: does the above definition work together with enums?

Seems like a natural fit insofar as both are subtype constraints.

: my Cyclic[7] enum DayOfWeek <Mon Tue Wed Thu Fri Sat Sun>;
: my DayOfWeek $day = Fri;
: say "Fri = {$day}, Sat = {$day + 1}, Sun = {$day + 2}, Mon = {$day + 3}";
: 
: Does that say "Fri = Fri, Sat = Sat, Sun = Sun, Mon = Mon"?

I suspect that could be made to work as long as you don't also expect
DayOfWeek to have Int semantics, or the semantics of some further
subtype of DayOfWeek.  This is not valid inheritance here.

The basic problem is that our inheritance is trying to model Platonic
ideals, but as Aristotle pointed out, the real world doesn't actually
have much use for Platonic ideals in its actual workings...

Larry

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About