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
Hmm.
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.
--John
(Larry, a nod would be appreciated at this point)