Bob Rogers wrote:
I notice that this doesn't allow for anonymous classes, since provision is made only for named classes. Is anonymous class support in prospect?
You can't use an anonymous class as a type for multisub dispatch because they don't have a name to dispatch on. A case could be made for anonymous multimethod dispatch, since the list of multi candidates is stored in the class of the first invocant.
(The PDD does mention C<push_pmc> as the PIR API for adding methods to multisubs, but such a sub must have already been declared :multi, with named classes, so the C<push_pmc> will have been done automatically anyway by the loader.) To define a methods that dispatch on anonymous classes, one would need to be able to pass an ordinary (non-:multi) sub and an array of class objects to the method-adding method. Since it is syntactically illegal to put ":invocant" on non-multi subs, either this restriction would have to be lifted, or some other means of declaring invocant args would be needed, perhaps using a distinguished non-class value in the class list.
A .sub has to be declared :multi to be used as a multi sub, even if stored as a method. We could provide a dummy type "SELF" that narrowly restricts the type match to the class of the first invocant, but it's only meaningful when :method and :multi are combined.
BTW, shouldn't there be a requirement that the number of classes in the :multi attribute match the number of :invocant params? If not, what does this mean?
Yes, the :multi attribute must specify as many types as the .sub has invocants (keeping in mind that the method invocant also counts as an invocant).
As Klaas-Jan pointed out, the magical "_" is not documented. But I think we need a better way to specify "any type". First of all, there is no way to say "any PMC type" as distinguished from "any register type" and "any type at all" (I think "_" means the last alternative, true?). Secondly, these types need explicit class names that point to explicit class objects, at which point special-casing for "_" (among other things) becomes unnecessary.
It's possible to create a variety of pseudo-classes for groupings that aren't strictly relations of inheritance or composition. But, better to wait for a specific practical use and implement it when needed.
For the most part, multiple dispatch at least needs to verify some minimal interface in its invocants, even if that requirement is as simple as "can act like a number", so differentiating on register type may not be very useful. Roles are likely to play a strong part.
And somewhere, maybe not here, the type network of all Parrot built-ins needs to be specified. This amounts to casting it in stone, but if we don't do it explicitly, it will be effectively cast in stone by virtue of all the code that will break if we try to change it.
Builtin operations or builtin types? For the types, see PDD 17. We won't cast anything in stone, but a change to the type hierarchy would have a longer deprecation cycle than more trivial changes.
Finally, a question: What is the difference between an :invocant parameter that isn't specialized (i.e. specifies "_" as the :multi dispatch class), and leaving that parameter out of the :multi list altogether? In other words, is there any practical difference between this: .sub test1 :multi(Integer, _, Integer) .param pmc i1 :invocant .param pmc x2 :invocant .param pmc i3 :invocant . . . .end and this: .sub test1 :multi(Integer, Integer) .param pmc i1 :invocant .param pmc x2 .param pmc i3 :invocant . . . .end
The latter example, with a non-invocant separating two invocants, isn't allowed.
Allison