MO bridge landing!
After 3 months of delay, it was quite amusing that the initial MO bridge took only 3 hours to land:
pugs> vv('hello, world').HOW
^Str
pugs> vv('hello, world').HOW.HOW
^Class
(The vv() above is a makeshift call that casts 6.2.0-land values into 6.28.0-land objects; it will go away once all existing built-in types are wrapped into MO.)
To understand what the ^Class notation means, let's take a brief look at Perl 6's object model, as implemented by Pugs 6.28.0's MO (Meta Object) subsystem.
In a traditional class-based object system such as Ruby's, the String class would be an instance of the Class class:
irb(main)> String.instance_of?(Class) => true irb(main)> String.instance_of?(String) => false
Because of this, you can't call .new on a String instance, and you can't call .length on the String class:
irb(main)> String.new.new NoMethodError: undefined method `new' for "":String irb(main)> String.new.length => 0 irb(main)> String.length NoMethodError: undefined method `length' for String:Class
Perl 5, on the other hand, takes an unique approach: When we say IO::String->new, the IO::String is not a Class object -- rather, it is a prototypical IO::String object that has no attributes!
IO::String->isa('Class');
#=> false (perl5 doesn't have a built-in Class)
IO::String->isa('IO::String');
#=> true
IO::String->new->new;
#=> IO::String=GLOB(0x18ab160)
IO::String->new->getpos;
#=> 0
IO::String->getpos;
Error: Can't use string ("IO::String") as a symbol ref...
The advantage of this arrangement is that several object systems -- prototype-based, closure-based, et cetera -- can exist simultaneously in the same program, without having to inherit from an universal Class class.
However, a bare literal "IO::String" is a terrible way to represent a prototypical object: it makes reflection needlessly difficult, and the error message for accessing the non-existing attribute slot ("Can't use string as a symbol ref...") seems to obey the principle of most surprise.
Perl 6's solution to this is simple: The prototypical string object, spelled ::Str or simply Str (if it's in scope), is a genuine Str instance. However, any attempt to access its attributes raises a sensible exception. Just as in Perl 5, so-called class methods such as .new are simply those methods that does not access instance attributes, and you can call them on both ::Str and regular Str instances.
Calling an object's WHAT method returns the prototypical object. This replaces Perl 5's ugly ref($x) || $x idiom:
pugs> 'hello'.WHAT ::Str pugs> Str.WHAT ::Str
On the other hand, because Perl 6's builtin objects are backed by a normal class-based dispatch system, you can reliably obtain a list of all Str's supported methods, by querying the Class instance that implements ::Str:
pugs> vv('hello').HOW
^Str
pugs> vv('hello').HOW.methods
["HOW","WHICH","bless","reverse"]
So there we have it: the Perl5ish prototypical object Str.WHAT is also spelled ::Str, and the Rubyish class object Str.HOW is also spelled ^Str.
The next step is to expose all MO's meta-objects (Role/Method/Class/Object) into Perl 6 land, and adapt our Perl 5 bridge to use Moose.pm, such that a class Foo {...} declaration in Pugs can generate both Haskell-side and Perl5-side representations, and work seamlessly with libraries on either side. Stay tuned!

Recent Comments