I wonder how an object can change its type without loosing its
identity. Consider two types Rectangle and Polygon with Rectangle
a subtype of Polygon. Now if there is a method add_vertex in the
Polygon type, calling it on a Rectangle warps the object out of
the Rectangle type into a Polygon with five vertices. How does
the implementation of Rectangle::add_vertex achieve this type
warp?
For a subset type the warping might occur automatically because
the where clause fails:
subset Rectangle of Polygon where { .num_vertices == 4 && ... }
A class type might just call self.bless(Polygon) after adapting
the internal representation. But how does an object loose a role?
Should there be an undoes or strip operator that does the inverse
of runtime role composition?
Have a nice weekend.
--
What is the point of declaring a type as Rectangle, with those
limitations, if you are going to mutate it into not being a Rectangle.
Calling add_vertex() on a mutating Rectangle should necessarily die.
The better approach would be one of:
1. The user explicitly casts the Rectangle into a Polygon, and then
invokes the add_vertex() on it.
2. The Polygon class is immutable, and add_vertex() will create and
return a new Polygon object with those properties, and the original
is still the Rectangle.
-- Darren Duncan
Darren Duncan wrote:
> What is the point of declaring a type as Rectangle, with those
> limitations, if you are going to mutate it into not being a Rectangle.
There are three issues:
1) the subtyping relation
2) the preservation of object identity
3) the mutating add_vertex method
> Calling add_vertex() on a mutating Rectangle should necessarily die.
This would drop 3) above, which is a violation of 1) as well if you
consider throwing exceptions as type error.
> The better approach would be one of:
>
> 1. The user explicitly casts the Rectangle into a Polygon, and then
> invokes the add_vertex() on it.
That is dropping 1) above. The same as my approach but non-automatic.
> 2. The Polygon class is immutable, and add_vertex() will create and
> return a new Polygon object with those properties, and the original is
> still the Rectangle.
That drops 2) above, and aligns the type of add_vertex to
:(Rectangle --> Polygon) in a pure setting. But I want this signature
and all of the above in the sense that an object stays a subtype of
Polygon all the time. Actually the return type is the type of the object
*after* the call. So it's equivalent to $pg = $pg.add_vertex($x,$y).
Note that this doesn't work when $pg is a Rectangle variable. The same
applies to my approach even without assignment.
So, one question remains unanswered: how does one achieve to get rid of
a role? The subset case works automatically and the class case through
.bless, I guess. Or is re-blessing not allowed? Note that a Rectangle
type might offer things like .width and .height or a simplified .area
implementation.
Another very interesting point is that the vertex array might be
available as a @.vertices array with the corresponding rw accessors
so that the type morphing needs to trap e.g. Array::push calls. How
would that be coded?
Regards, TSa.
--