TSa Thomas.Sandlass-at-barco.com |Perl 6| wrote:
Hmm? I meant Num ∩ Str. This intersection type is a subtype of
Str and Num without type coercion and it beats both in specificity
when it comes to dispatch.

There are methods in Str that are not in Num, and vice versa. A variable declared as Num Str will accept methods of either without compile-time complaint (but will give run-time error if the type is wrong). A type of Num ∩ Str, which does not exist directly in the synopses but you could code one up from scratch introspect both metaobjects and copy the member list intersection, as a CPAN library perhaps, would give a compile-time error if you wrote the use of a method that was not in both Num and Str. There would be no need for a run-time check.

"10".HOW returns something that does the Metaobject role, which itself can stringify to the name of the Perl 6 class in this case, but the details depend of the object system. In a JavaScript or Self object model, there might not be classes. But what it stringifies to isn't really discussed.

Yes. It returns the instance manager since instance management is the
prime task of a class.

"10".WHAT returns the undefined prototype of Str. It also stringifies to the short name of the class.

I had hoped that WHAT denotes a more specific type than HOW. E.g.

The synopses imply the other way around. But not in the same way you discuss next.

   subset ThreeChars of Str where {$_.elems == 3}

   my ThreeChars $x = 'xxx';

   $x.WHAT;  # ThreeChars
   $x.HOW;   # Str

   $x === 'xxx'; # false because type i.e. the WHAT
                 # has to be the same


It were interesting to know what $x.new returns. If that dispatches
to Str the result is '' which is not a ThreeChars. So how does the
subset declaration make it return e.g. '   '? Looks like one needs
more than a subset declaration to make a proper subtype ;)

Indeed. That would be true about all methods that returned the original type.

Using Str by itself is a listop with no parameters and returns the undefined prototype. So

say "10".WHAT === Str;

prints True. Both refer to the same value: the undefined prototype object of type Str. If the undefined prototype is guaranteed to be singular, then =:= would also show True.

Sounds reasonable. The HOW behind Str might e.g. be PerlStr.

say "10".HOW === Str;

prints False. The left side is a Metaobject, the right a Str mixed in with something that delegates class methods and overrides stringification etc. The things you can call on them are different. They could not be implemented as the same object.

How would Str be implemented then? It is more concrete than a role but
more abstract than a class.

Str is a package, that is a module that is a class.

The implementation, on a deep level, sees a class name used as a listop and figures out what to call based on rules specific for that, not explained completely or well in the synopses, but generally looks for conversion functions in one direction with the first argument as the invocant (there isn't one, so that's nil) and in the other direction in that class. Whatever the detailed rules are, it knows in this case (no arguments) to call some class method in Str for that purpose, which is created automatically or inherited from Object or some combination of the two. That function returns the undefined protoobject for its class. I imagine the implementation generates a function in the class that returns a single instance, also made up at the time the class is created.

So if I may continue, I hazard that a package that is a class has a package variable with a reserved internal name that points to the metaobject. The metaobject does the metaobject role, which defines all the stuff the synopses say it can perform, but the concrete type is unspecified, and probably some internal class specific to the use of P6opaque-blessed classes.

Meanwhile, the grammar knows that a type name (a package name) may serve as a listop, and this usage is noted specifically in the AST. The code generator sees that AST node and knows to search for which function to actually call based on the rules for conversion functions, and codes the one it found.

The grammar knows that a package name (or perhaps just a class name) can be used in various ways, and allows this in the generated AST. Whether the use of a package rather than a variable (for example) is encoded specifically in the AST, or if the next step looks at what the identifier actually is, doesn't matter -- it knows to generate lookups and function calls with that innate meaning. That is Dog.foo will actually generate code for $Dog::__METAOBJECT<__classmethods><foo>, where Dog is not just a package, __METAOBJECT is the special variable mentioned earlier. All the lookups are resolved at compile time, so at run time it just calls the proper function. The code generator knows the way classes are made.

So it's not as closed in on itself as LISP or even Smalltalk. That is due to the by-design abstraction of the metaobject with freedom to write one from scratch, and due to the rich natural-language-like syntax rather than having the syntax exactly match the representation.


(Larry, a nod would be appreciated at this point)

Reply via email to