Some comments about the vtable PDD...
First a general comment. I think we really need to make it clear for
each method, which arg respresents the object that is having its method
called (ie which is $self/this so to speak). One way to make this clear
would be to insist that the first arg is always $self,
but failing that, it should be explicity mentioned for each function.
Also, can I suggest a bit of terminology, which I will use below?
I define an *empty* PMC as a PMC which exists, but does not have a valid
vtable ptr or content (and so whose methods must not be called under
any circumstances). I specifically contrast this with a undefined PMC,
which has a valid vtable pointer that points to a bunch of methods that
mostly call carp("use of undefined value ...").
Now onwards and upwards....
> The C<key> parameter is optional, and if passed it refers to an array
> of key structure pointers.
A mere detail, but would it not be more efficient to just pass them
as extra args, ie add(PMC1, PMC2, PMC3, key1, key2, key3),
rather than having to potentially create and populate a tmp struct
just to call the function???
> IV type(PMC[, subtype]);
>
> Returns the type of the PMC. If the subtype is passed (int, string,
> num) it returns the subtype of the PMC. This is generally a class
> function rather than a variable one, but the PMC is passed in just in
> case. (And so we can have the subtype be a vararg parameter)
I dont understand the subtype bit. If for example we pass an optional
2nd arg of INT (assuming this is some sort of enum?), what does type()
return?
> =item new
>
> void new(PMC[, key]);
>
> Creates a new variable of the appropriate type out of the passed PMC,
> destroying the current contents if there are any. This is a class
> function.
As an aside, am I right in assuming that there will be a function somewhere
(outside the scope of this PDD) that creates new, empty PMCs, which can then
be acted upon by new() to turn them into PMCs of a particular type?
Will PMCs that have just been new()ed have a default null value, eg
0/"" ? Note that they wont be undefined - at least, I'm assuming that
undefined is handled by a separate class.
Perhaps we need instead a range of new()s that initialise to various
string, numeric etc values?
The above definition of new() implies that it first calls destroy()
to release any previous contents. I think it would be better to define
new() as operating on an empty PMC (so it is the the caller's responsibility
to call destroy() first, if necessary).
Actually, I suspect that the whole area of new/clone/destroy etc will need to
be examined carefully in the light of a 'typical' variable lifecycle,
to avoid to unecessary transitions. For example, my $a = 'abc' might
involve $a going from empty -> undef -> empty -> "" -> "abc" or similar,
if we're not careful.
> void clone(PMC1, PMC2 [, int flags[,key]);
>
> Copies C<PMC2> into C<PMC1>. The C<flags> parameter notes whether
> a deep copy should be done. (Possibly other things as well, if someone
> thinks of something reasonable)
One flag that would be very useful is 'destroy', which tells clone() to
destroy PMC2 immediately after the clone operation.
This is because a clone will often be immediately followed by a destroy
of the copied PMC, and delegating the destory() to clone() allows clone()
the chance to do things more effiently (eg even when asked to do a deep
copy, it just copies the vtable pointer and payload pointer(s), then scrubs
the old PMC)
I alo think that clone should expect PMC1 to be empty - ie it assumes the
caller has already called destroy() if necessary.
I guess we also need an assign() method, to handle
$a = $b and the like.
Note that assign and clone are very different operations (although assign
may well call clone): assign() copies *to* itself, while clone() copies
*from* itself.
Note that if $a is a 'simple' variable, $a->assign($b) will
itself just fall through to $b->clone($a) and let $a be wiped; while
if $a is magic or tied or whatever, then $a->assign($b) will take
a more active role in setting its own value, based on the value of $b.
> void morph(PMC, type[, key]);
>
> Tells the PMC to change itself into a PMC of the specified type.
I dont really see what the difference is between this and new().
> void destroy(PMC[, key]);
>
> Destroys the variable the PMC represents, leaving it undef.
(See also my comments earlier about new/clone/destroy etc).
I think destroy should leave an empty PMC rather than an undef one,
since as I said earlier, I think undef is a class in its own right.
> =item exists (x)
>
> BOOL exists(PMC1[, key]);
Presumably we also need defined(). (where most classes will always return
false, while the 'undefined' classs class always returns true.)