Perl.com 
 Published on Perl.com http://www.perl.com/pub/a/2004/04/16/a12.html
See this if you're having trouble printing code examples

 

Apocalypse 12
By Larry Wall
April 16, 2004

Editor's Note: this Apocalypse is out of date and remains here for historic reasons. See Synopsis 12 for the latest information.

by Larry Wall

Editor's Note: this Apocalypse is out of date and remains here for historic reasons. See Synopsis 12 for the latest information.

The official, unofficial slogan of Perl 6 is "Second System Syndrome Done Right!". After you read this Apocalypse you will at least be certain that we got the "Second System" part down pat. But we've also put in a little bit of work on the "Done Right" part, which we hope you'll recognize. The management of complexity is complex, but only if you think about it. The goal of Perl 6 is to discourage you from thinking about it unnecessarily.

Speaking of thinking unnecessarily, please don't think that everything we write here is absolutely true. We expect some things to change as people point out various difficulties. That's the way all the other Apocalypses have worked, so why should this one be different?

When I say "we", I don't just mean "me". I mean everyone who has participated in the design, including the Perl 6 cabal, er, design team, the readers (and writers) of the perl6-language mailing list, and all the participants who wrote or commented on the original RFCs. For this Apocalypse we've directly considered the following RFCs:


    RFC  PSA  Title
    ===  ===  =====
    032  abb  A Method of Allowing Foreign Objects in Perl
    067  abb  Deep Copying, a.k.a., Cloning Around
    092  abb  Extensible Meta-Object Protocol
    095  acc  Object Classes
    101  bcc  Apache-Like Event and Dispatch Handlers
    126  aaa  Ensuring Perl's Object-Oriented Future
    137  bdd  Overview: Perl OO Should <Not> Be Fundamentally Changed
    147  rr   Split Scalars and Objects/References into Two Types
    152  bdd  Replace Invocant in @_ with self() builtin
    163  bdd  Objects: Autoaccessors for Object Data Structures
    171  rr   My Dog $spot Should Call a Constructor Implicitly
    174  bdd  Improved Parsing and Flexibility of Indirect Object Syntax
    187  abb  Objects : Mandatory and Enhanced Second Argument to C<bless>
    188  acc  Objects : Private Keys and Methods
    189  abb  Objects : Hierarchical Calls to Initializers and Destructors
    190  acc  Objects : NEXT Pseudoclass for Method Redispatch
    193  acc  Objects : Core Support for Method Delegation
    223  bdd  Objects: C<use invocant> Pragma
    224  bdd  Objects : Rationalizing C<ref>, C<attribute::reftype>, and
                C<builtin:blessed>
    244  cdr  Method Calls Should Not Suffer from the Action on a Distance
    254  abb  Class Collections: Provide the Ability to Overload Classes
    256  abb  Objects : Native Support for Multimethods
    265  abc  Interface Polymorphism Considered Lovely
    277  bbb  Method Calls Should Suffer from Ambiguity by Default
    307  rr   PRAYER: What Gets Said When You C<bless> Something
    335  acc  Class Methods Introspection: What Methods Does this Object
                Support?
    336  bbb  Use Strict 'objects': A New Pragma for Using Java-Like
                Objects in Perl

These RFCs contain many interesting ideas, and many more "cries for help". Usually in these Apocalypses, I discuss the design with respect to each of the RFCs. However, in this case I won't, because most of these RFCs fail in exactly the same way--they assume the Perl 6 object model to be a set of extensions to the Perl 5 object model. But as it turns out, that would have been a great way to end up with Second System Syndrome Done Wrong. Perl 5's OO system is a great workbench, but it has some issues that have to be dealt with systematically rather than piecemeal.

Some of the Problems with Perl 5 OO

A little too orthogonal

It has often been claimed that Perl 5 OO was "bolted on", but that's inaccurate. It was "bolted through", at right angles to all other reference types, such that any reference could be blessed into being an object. That's way cool, but it's often a little too cool.

Not quite orthogonal enough

It's too hard to treat built-in types as objects when you want to. Perl 5's tie interface helps, but is suboptimal in several ways, not the least of which is that it only works on variables, not values.

Forced non-encapsulation

Because of the ability to turn (almost) anything into an object, a derived class had to be aware of the internal data type of its base class. Even after convention settled on hashes as the appropriate default data structure, one had to be careful not to stomp on the attributes of one's base class.

A little too minimal

Some people will be surprised to hear it, but Perl is a minimalist language at heart. It's just minimalistic about weird things compared to your average language. Just as the binding of parameters to @_ was a minimalistic approach, so too the entire Perl 5 object system was an attempt to see how far you could drive a few features. But many of the following difficulties stem from that.

Too much keyword reuse

In Perl 5, a class is just a package, a method is just a subroutine, and an object is just a blessed referent. That's all well and good, and it is still fundamentally true in Perl 6. However, Perl 5 made the mistake of reusing the same keywords to express similar ideas. That's not how natural languages work--we often use different words to express similar ideas, the better to make subtle distinctions.

Too difficult to capture metadata

Because Perl 5 reused keywords and treated parameter binding as something you do via a list assignment at runtime, it was next to impossible for the compiler to tell which subroutines were methods and which ones were really just subroutines. Because hashes are mutable, it was difficult to tell at compile time what the attribute names were going to be.

Inside-out interfaces

The Perl 5 solution to the previous problem was to declare more things at compile time. Unfortunately, since the main way to do things at compile time was to invoke use, all the compile-time interfaces were shoehorned into use's syntax, which, powerful though it may be, is often completely inside-out from a reasonable interface. For instance, overloading is done by passing a list of pairs to use, when it would be much more natural to simply declare appropriate methods with appropriate names and traits. The base and fields pragmas are also kludges.

Not enough convention

Because of the flexibility of the Perl 5 approach, there was never any "obvious" way to do it. So best practices had to be developed by each group, and of course, everyone came up with a slightly different solution. Now, we're not going to be like some folks and confuse "obvious" with "the only way to do it". This is still Perl, after all, and the flexibility will still be there if you need it. But by convention, there needs to be a standard look to objects and classes so that they can interoperate. There's more than one way to do it, but one of those is the standard way.

Wrong conventions

The use of arrow where most of the rest of the world uses dot was confusing.

Everything possible, but difficult

The upshot of the previous problems was that, while Perl 5 made it easy to use objects and classes, it was difficult to try to define classes or derive from them.

Perl 5 Non-Problems

While there are plenty of problems with Perl 5's OO system, there are some things it did right.

Generating class by running code at compile time

One of the big advances in Perl 5 was that a program could be in charge of its own compilation via use statements and BEGIN blocks. A Perl program isn't a passive thing that a compiler has its way with, willy-nilly. It's an active thing that negotiates with the compiler for a set of semantics. In Perl 6 we're not shying away from that, but taking it further, and at the same time hiding it in a more declarative style. So you need to be aware that, although many of the things we'll be talking about here look like declarations, they trigger Perl code that runs during compilation. Of such methods are metaclasses made. (While these methods are often triggered by grammar rule reductions, remember from Apocalypse 5 that all these grammar rules are also running under the user's control. You can tweak the language without the crude ax of source filtering.)

There are many roads to polymorphism

In looking for an "obvious" way to conventionalize Perl's object system, we shouldn't overlook the fact that there's more than one obvious way, and different approaches work better in different circumstances. Inheritance is one way (and typically the most overused), but we also need good support for composition, delegation, and parametric types. Cutting across those techniques are issues of interface, implementation, and mixtures of interface and implementation. There are multiple strategies for ambiguity resolution as well, and no single strategy is always right. (Unless the boss says so.)

People using a class shouldn't have to think hard

In making it easier to define and derive classes, we must be careful not to make it harder to use classes.

Trust in Convention, But Keep Your Powder Dry

So to summarize this summary, what we're proposing to develop is a set of conventions for how object orientation ought to work in Perl 6--by default. But there should also be enough hooks to customize things to your heart's content, hopefully without undue impact on the sensibilities of others.

And in particular, there's enough flexibility in the new approach that, if you want to, you can still program in a way much like the old Perl 5 approach. There's still a bless method, and you can still pretend that an object is a hash--though it isn't anymore.

However, as with all the rest of the design of Perl 6, the overriding concern has been that the language scale well. That means Perl has to scale down as well as up. Perl has to work well both as a first language and as a last language. We believe our design fulfills this goal--though, of course, only time will tell.

One other note: if you haven't read the previous Apocalypses and Exegeses, a lot of this is going to be complete gobbledygook to you. (Of course, even if you have read them, this might still be gobbledygook. You take your chances in life...)

An Easy Example

Before we start talking about all the hard things that should be possible, let's look at an example of some of the easy things that should be easy. Suppose we define a Point object that (for some strange reason) allows you to adjust the y-axis but not the x-axis.


    class Point {
        has $.x;
        has $.y is rw;

        method clear () { $.x = 0; $.y = 0; }
    }

    my $point = Point.new(x => 2, y => 3);

    $a = $point.y;      # okay
    $point.y = 42;      # okay

    $b = $point.x;      # okay
    $point.x = -1;      # illegal, default is read-only

    $point.clear;       # reset to 0,0

If you compare that to how it would have to be written in Perl 5, you'll note a number of differences:

Now suppose we want to derive from Point, and add a z-axis. That's just:


    class Point3d is Point {
        has $:z = 123;
        method clear () { $:z = 0; next; }
    }
    my $point3d = Point3d.new(x => 2, y => 3, z => 4);
    $c = $point3d.z;    # illegal, $:z is invisible

The implicit constructor automatically sorts out the named arguments to the correct initializers for you. If you omit the z value, it will default to 123. And the new clear method calls the old clear method merely by invoking next, without the dodgy "super" semantics that break down under MI. We also declared the $:z attribute to be completely private by using a colon instead of a dot. No accessor for it is visible outside the class. (And yes, OO purists, our other attributes should probably have been private in the first place...that's why we're making it just as easy to write a private attribute as a public one.)

If any of that makes your head spin, I'm sure the following will clear it right up. :-)

by Larry Wall

Editor's Note: this Apocalypse is out of date and remains here for historic reasons. See Synopsis 12 for the latest information.

Classes

A class is what provides a name and a place for the abstract behavior of a set of objects said to belong to the class.

As in Perl 5, a class is still "just a funny package", structurally speaking. Syntactically, however, a class is now distinct from a package or a module. And the body of a class definition now runs in the context of a metaclass, which is just a way of saying that it has a metaclass instance as its (undeclared) invocant. (An "invocant" is what we call the object or class on behalf of which a method is being called.) Hence class definitions, though apparently declarative, are also executing code to build the class definition, and the various declarations within the class are also running bits of code. By convention classes will use a standard metaclass, but that's just convention. (A very strong convention, we hope.)

The primary role of a class is to manage instances, that is, objects. So a class must worry about object creation and destruction, and everything that happens in between. Classes have a secondary role as units of software reuse, in that they can be inherited from or delegated to. However, because this is a secondary role, and because of weaknesses in models of inheritance, composition, and delegation, Perl 6 will split out the notion of software reuse into a separate class-like entity called a "role". Roles are an abstraction mechanism for use by classes that don't care about the secondary aspects of software reuse, or that (looking at it the other way) care so much about it that they want to encapsulate any decisions about implementation, composition, delegation, and maybe even inheritance. Sounds fancy, but just think of them as includes of partial classes, with some safety checks. Roles don't manage objects. They manage interfaces and other abstract behavior (like default implementations), and they help classes manage objects. As such, a role may only be composed into a class or into another role, never inherited from or delegated to. That's what classes are for.

Classes are arranged in an inheritance hierarchy by their "isa" relationships. Perl 6 supports multiple inheritance, but makes it easy to program in a single-inheritance style, insofar as roles make it easy to mix in (or delegate, or parameterize) private implementation details that don't belong in the public inheritance tree.

In those cases where MI is used, there can be ambiguities in the pecking order of classes in different branches. Perl 6 will have a canonical way to disambiguate these, but by design the dispatch policy is separable from inheritance, so that you can change the rules for a given set of classes. (Certainly the rules can change when we call into another language's class hierarchy, for instance.)

Where possible, class names are treated polymorphically, just as method names are. This powerful feature makes it possible to inherit systems of classes in parallel. (These classes might be inner classes, or they might be inner aliases to outer classes.) By making the class names "virtual", the base classes can refer to the appropriate derived classes without knowing their full name. That sounds complicated, but it just means that if you do the normal thing, Perl will call the right class instead of the one you thought it was going to call. :-)

(As in C++ culture, we use the term "virtual" to denote a method that dispatched based on the actual runtime type of the object rather than the declared type of the variable. C++ classes have to declare their methods to be virtual explicitly. All of Perl's public methods are virtual implicitly.)

You may derive from any built-in class. For high-level object classes such as Int or Num there are no restrictions on how you derive. For low-level representational classes like int or num, you may not change the representation of the value; you may only add behaviors. (If you want to change the representation, you should probably be using composition instead of inheritance. Or define your own low-level type.) Apart from this, you don't need to worry about the difference between int and Int, or num and Num, since Perl 6 will do autoboxing.

Declaration of Classes

Class declarations may be either file scoped or block scoped. A file-scoped declaration must be the first thing in the file, and looks like this:


    class Dog is Mammal;
    has Limb @.paws;
    method walk () { .paws».move() }

That has the advantage of avoiding the use of one set of braces, letting you put everything up against left margin. It is otherwise identical to a block-scoped class, which looks like this:


    class Dog is Mammal {
        has Limb @.paws;
        method walk () { .paws».move() }
    }

An incomplete class definition makes use of the ... ("yada, yada, yada") operator:


    class Dog is Mammal {...}

The declaration of a class name introduces the name as a valid bare identifier or name. In the absence of such a declaration, the name of a class in an expression must be introduced with the :: class sigil, or it will be considered a bareword and rejected, since Perl 6 doesn't allow barewords. Once the name is declared however, it may be used as an ordinary term in an expression. Unlike in Perl 5, you should not view it as a bareword string. Rather, you should view it as a parameterless subroutine that returns a class object, which conveniently stringifies to the name of the class for Perl 5 compatibility. But when you say


    Dog.new()

the invocant of new is an object of type Class, not a string as in Perl 5.

Unmodified, a class declaration always declares a global name. But if you prefix it with our, you're defining an inner class:


    class Cell {
        our class Golgi {...}
        ...
    }

The full name of the inner class is Cell::Golgi, and that name can be used outside of Cell, since Golgi is declared in the Cell package. (Classes may be declared private, however. More later.)

Class traits

A class declaration may apply various traits to the class. (A trait is a property applied at compile time.) When you apply a trait, you're accepting whatever it is that that trait does to your class, which could be pretty much anything. Traits do things to classes. Do not confuse traits with roles, which are sworn to play a subservient role to the class. Traits can do whatever they jolly well please to your class's metadata.

Now, the usual thing to do to a class's metadata is to insert another class into its ISA metadata. So we use trait notation to install a superclass:


    class Dog is Mammal {...}

To specify multiple inheritance, just add another trait:


    class Dog is Mammal is Pet {...}

But often you'll want a role instead, specified with does:


    class Dog is Mammal does Pet {...}

More on that later. But remember that traits are evil. You can have traits like:


    class Moose is Mammal is stuffed is really(Hatrack) is spy(Russian) {...}

So what if you actually want to derive from stuffed? That's a good question, which we will answer later. (The short answer is, you don't.)

Now as it happens, you can also use is from within the class. You can also put the does inside to include various roles:


    class Dog {
        is Mammal;
        does Pet;
        does Servant;
        does Best::Friend[Man];
        does Drool;
        ...
    }

In fact, there's no particular reason to put any of these outside the braces except to make them more obvious to the casual reader. If we take the view that inheritance is just one form of implementation, then a simple


    class Dog {...}

is sufficient to establish that there's a Dog class defined out there somewhere. We shouldn't really care about the implementation of Dog, only its interface--which is usually pretty slobbery.

That being said, you can know more about the interface at compile time once you know the inheritance, so it's good to have pulled in a definition of the class as well as a declaration. Since this is typically done with use, the inheritance tree is generally available even if you don't mark your class declaration externally with the inheritance. (But in any event, the actual inheritance tree doesn't have to be available till runtime, since that's when methods are dispatched. (Though as is often the case, certain optimizations work better when you give them more data earlier...))

Use of Classes

A class is used directly by calling class methods, and indirectly by calling methods of an object of that class (or of a derived class that doesn't override the methods in question).

Classes may also be used as objects in their own right, as instances of a metaclass, the class MetaClass by default. When you declare class Dog, you're actually calling a metaclass class method that constructs a metaclass instance (i.e., the Dog class) and then calls the associated closure (i.e., the body of the class) as a method on the instance. (With a little grammatical magic thrown in so that Dog isn't considered a bareword.)

The class Dog is an instance of the class MetaClass, but it's also an instance of the type Class when you're thinking of it as a dispatcher. That is, a class object is really allomorphic. If you treat one as an instance of Class, it behaves as if it were the user's view of the class, and the user thinks the class is there only to dispatch to the user's own class and instance methods. If, however, you treat the object as an instance of MetaClass, you get access to all its metaclass methods rather than the user-defined methods. Another way to look at it is that the metaclass object is a separate object that manages the class object. In any event, you can get from the ordinary class object to its corresponding metaclass object via the .meta method, which every object supports.

By the way, a Class is a Module, which in turn is a Package, which in turn is an Object. Or something like that. So a class can always be used as if it were a mere module or package. But modules and packages don't have a .dispatch method...

By default, classes in Perl are left open. That is, you can add more methods later. (However, an application may close them.) For discussion of this, see the section on "Open vs. Closed Classes".

Class Name Semantics

Class names (and module names) are just package names.

Unlike in Perl 5, when you mention a package name in Perl 6 it doesn't always mean a global name, since Perl 6 knows about inner classes and lexically scoped packages and such. As with other entities in Perl such as variables and methods, a scan is made for who thinks they have the best definition of the name, going out from lexical scopes to package scope to global scope in the case of static class names, and via method inheritance rules in the case of virtual class names.

Note that ::MyClass and MyClass mean the same thing. In Perl 6, an initial :: is merely an optional sigil for when the name of the package would be misconstrued as something else. It specifically does not mean (as it does in Perl 5) that it is a top-level package. To refer to the top-level package, you would need to say something like ::*MyClass (or just *MyClass in places where the * unary operator would not be expected.) But also note that the * package in Perl is not the "main" package in the Perl 5 sense.

Likewise, the presence of :: within a package name like Fish::Carp does not make it a global package name necessarily. Again, it scans out through various scopes, and only if no local scopes define package Fish::Carp do you get the global definition. And again, you can force it by saying ::*Fish::Carp. (Or just *Fish::Carp in places where the * unary operator is not expected.)

You can interpolate a parenthesized expression within a package name after any ::. So, these are all legal package names (or module names, or class names):


    ::($alice)
    ::($alice)::($bob)
    ::($alice::($bob))
    ::*::($alice)::Bob
    ::('*')::($alice ~ '_misc')::Bob
    ::(get_my_dir())
    ::(@multilevel)

And any of those package names could be part of a variable or sub name:


    $::($alice)::name
    @::($alice)::($bob)::elems[1,2,3]
    %::*::($alice)::Bob::map{'xyz'}
    &::('*')::($alice ~ '_misc')::Bob::doit(1,2,3)
    $::(get_my_dir())::x
    $::(@multilevel)

Note in the last example that the final element of @multilevel is taken to be the variable name. This may be illegal under use strict refs, since it amounts to a symbolic reference. (Not that the others aren't symbolic, but the rules may be looser for package names than for variable names, depending on how strict our strictures get.)

by Larry Wall

Editor's Note: this Apocalypse is out of date and remains here for historic reasons. See Synopsis 12 for the latest information.

Private Classes

A class named with a single initial colon is a private class name:


    class :MyPrivateClass {...}

It is completely ignored outside of the current class. Since the name is useful only in the current package, it makes no sense to try to qualify it with a package name. While it's an inner class of sorts, it does not override any class name from any other class because it lives in its own namespace (a subnamespace of the current package), and there's no way to tell if the class you're deriving from declares its own private class of the same name (apart from digging through the reflection interfaces).

The colon is orthogonal to the scoping. What's actually going on in this example is that the name is stored in the package with the leading colon, because the colon is part of the name. But if you declared "my class :Golgi" the private name would go into the lexical namespace with the colon. The colon functions a bit like a "private" trait, but isn't really a trait. Wherever you might use a private name, the colon in the name effectively creates a private subspace of names, just as if you'd prefixed it with "_" in the good old days.

But if were only that, it would just be encapsulation by convention. We're trying to do a little better than that. So the language needs to actively prevent people from accessing that private subspace from outside the class. You might think that that's going to slow down all the dispatchers, but probably not. The ordinary dispatch of Class.method and $obj.method don't have to worry about it, because they use bare identifiers. It's only when people start doing ::($class) or $obj.$method that we have to trap illegal references to colonic names.

Even though the initial colon isn't really a trait, if you interrogate the ".private" property of the class, it will return true. You don't have to parse the name to get that info.

We'll make more of this when we talk about private methods and attributes. Speaking of methods...

Methods

Methods are the actions that a class knows how to invoke on behalf of an object of that type (or on behalf of itself, as a class object). But you knew that already.

As in Perl 5, a method is still "just a funny subroutine", but in Perl 6 we use a different keyword to declare it, both because it's better documentation, and because it captures the metadata for the class at compile time. Ordinary methods may be declared only within the scope of a class definition. (Multimethods are exempt from this restriction, however.)

Declaration of Methods

To declare a method, use the method keyword just as you would use sub for an ordinary subroutine. The declaration is otherwise almost identical:


    method doit ($a, $b, $c) { ... }

The one other difference is that a method has an invocant on behalf of which the method is called. In the declaration above, that invocant is implicit. (It is implicitly typed to be the same as the current surrounding class definition.) You may, however, explicitly declare the invocant as the first argument. The declaration knows you're doing that because you put a colon between the invocant and the rest of the arguments:


    method doit ($self: $a, $b, $c) { ... }

In this case, we didn't specify the type of $self, so it's an untyped variable. To make the exact equivalent of the implicit declaration, put the current class:


    method doit (MyClass $self: $a, $b, $c) { ... }

or more generically using the ::_ "current class" pronoun:


    method doit (::_ $self: $a, $b, $c) { ... }

In any case, the method sets the current invocant as the topic, which is also known as the $_ variable. However, the topic can change depending on the code inside the method. So you might want to declare an explicit invocant when the meaning of $_ might change. (For further discussion of topics see Apocalypse 4. For a small writeup on sub signatures see Apocalypse 6.)

A private method is declared with a colon on the front:


    method :think (Brain $self: $thought)

Private methods are callable only by the class itself, and by trusted "friends". More about that when we talk about attributes.

Use of Methods

As in Perl 5, there are two notations for calling ordinary methods. They are called the "dot" notation and the "indirect object" notation.

The dot notation

Perl 6's "dot" notation is just the industry-standard way to call a method these days. (This used to be -> in Perl 5.)


    $object.doit("a", "b", "c");

If the object in question is the current topic, $_, then you can use the unary form of the dot operator:


    for @objects {
        .doit("a", "b", "c");
    }

A simple variable may be used for an indirectly named method:


    my $dosomething = "doit";
    $object.$dosomething("a", "b", "c");

As in Perl 5, if you want to do anything fancier, use a temporary variable.

The parentheses may also be omitted when the following code is unambiguously a term or operator, so you can write things like this:


    @thumbs.each { .twiddle }   # same as @thumbs.each({.twiddle})
    $thumb.twiddle + 1          # same as $thumb.twiddle() + 1
    .mode 1                     # same as $_.mode(1)

(Parens are always required around the argument list when a method call with arguments is interpolated into a string.)

The parser will make use of whitespace at this point to decide some things. For instance


    $obj.method + 1

is obviously a method with no arguments, while


    $obj.method +1

is obviously a method with an argument. However, the dwimmery only goes as far as the typical person's visual intuition. Any construct too ambiguous is simply rejected. So


    $obj.method+1

produces a parse error.

In particular, curlies, brackets, or parens would be interpreted as postfix subscripts or argument lists if you leave out the space. In other words, Perl 6 distinguishes:


    $obj.method ($x + $y) + $z  # means $obj.method(($x + $y) + $z)

from


    $obj.method($x + $y) + $z   # means ($obj.method($x + $y)) + $z

Yes, this is different from Perl 5. And yes, I know certain people hate it. They can write their own grammar.

While it's always possible to disambiguate with parentheses, sometimes that is just too unsightly. Many methods want to be parsed as if they were list operators. So as an alternative to parenthesizing the entire argument list, you can disambiguate by putting a colon between the method call and the argument list:


    @thumbs.each: { .twiddle }  # same as @thumbs.each({.twiddle})
    $thumb.twiddle: + 1         # same as $thumb.twiddle(+ 1)
    .mode: 1                    # same as $_.mode(1)
    $obj.for: 1,2,3 -> $i { ... }

If a method is declared with the trait "is rw", it's an lvalue method, and you can assign to it just as if it were an ordinary variable:


    method mystate is rw () { return $:secretstate }

    $object.mystate = 42;
    print $object.mystate;      # prints 42

In fact, it's a general rule that you can use an argumentless "rw" method call anywhere you might use a variable:


    temp $state.pi = 3;
    $tailref = \$fido.tail;

(Though occasionally you might need to supply parentheses to disambiguate, since the compiler can't always know at compile time whether the method has any arguments.)

Method calls on container objects are obviously directed to the container object itself, not to the contents of the container:


    $elems = @array.elems;
    @keys  = %hash.keys;
    $sig   = &sub.signature;

However, with scalar variables, methods are always directed to the object pointed to by the reference contained in the scalar:


    $scalar = @array;           # (implied \ in scalar context)
    $elems = $scalar.elems;     # returns @array.elems

or for value types, the appropriate class is called as if the value were a reference to a "real" object.


    $scalar = "foo";
    $chars = $scalar.chars;     # calls Str::chars or some such

In order to talk to the scalar container itself, use the tied() pseudo-function as you would in Perl 5:


    if tied($scalar).constant {...}

(You may recall, however, that in Perl 6 it's illegal to tie any variable without first declaring it as tie-able, or (preferably) tying it directly in the variable's declaration. Otherwise the optimizer would have to assume that every variable has semantics that are unknowable in advance, and we would have to call it a pessimizer rather than an optimizer.)

by Larry Wall

Editor's Note: this Apocalypse is out of date and remains here for historic reasons. See Synopsis 12 for the latest information.

The "indirect object" notation

The other form of method call is known as the "indirect object" syntax, although it differs from Perl 5's syntax in that a colon is required between the indirect object (the invocant) and its arguments:


    doit $object: "a", "b", "c"

The colon may be omitted if there are no arguments (besides the invocant):


    twiddle $thumb;
    $x = new X;

Note that indirect object calls may not be directly interpolated into a string, since they don't start with a sigil. You can always use the $() expression interpolater though:


    say "$(greet $lang), world!";

As in Perl 5, the indirect object syntax is valid only if you haven't declared a subroutine locally that overrides the method lookup. That was a bit of a problem in Perl 5 since, if there happened to be a new constructor in your class, it would call that instead dispatching to the class you wanted it to. That's much less of a problem in Perl 6, however, because Perl 6 cannot confuse a method declaration with a subroutine declaration. (Which is yet another reason for giving methods their own keyword.)

Another factor that makes indirect objects work better in Perl 6 is that the class name in "new X" is a predeclared object, not a bare identifier. (Perl 5 just had to guess when it saw two bare identifiers in a row that you were trying to call a class method.)

The indirect object syntax may not be used with a variable for the methodname. You must use dot notation for that.

Because of precedence, the indirect object notation may not be used as an lvalue unless you parenthesize it:


    (mystate $object) = 42;
    (findtail Dog: "fido") = Wagging::on;

You may parenthesize an argumentless indirect object method to make it look like a function:


    mystate($object) = 42;
    twiddle($thumb);

The dispatch rules for methods and global multi subs conspire to keep these unambiguous, so the user really doesn't have to worry about whether


    close($handle);

is implemented as a global multi sub or a method on a $handle object. In essence, the multimethod dispatching rules degenerate to ordinary method dispatch when there are no extra arguments to consider (and sometimes even when there are arguments). This is particularly important because Perl uses these rules to tell the difference between


    print "Howdy, world!\n";    # global multi sub

and


    print $*OUT;                # ordinary filehandle method

However, you must still put the colon after the invocant if there are other arguments. The colon tells the parser whether to look for the arguments inside:


    doit($object: "a", "b", "c")

or outside:


    doit($object): "a", "b", "c"

If you do say


    doit($object, "a", "b", "c")

the first comma forces it to be interpreted as a sub call rather than a method call.

(We could have decided to say that whenever Perl can't find a doit() sub definition at runtime, it should assume you meant the entire parenthesized list to be the indirect object, which, since it's in scalar context would automatically generate a list reference and call [$object,"a","b","c"].doit(), which is unlikely to be what you mean, or even work. (Unless, of course, that's how you really meant it to work.) But I think it's much more straightforward to simply disallow comma lists at the top level of an indirect object. The old "if it looks like a function" rule applies here. Oddly, though, function syntax is how you call multisubs in Perl 6. And as it happens, the way the multisub/multimethod dispatch rules are defined, it could still end up calling $object.doit("a", "b", "c") if that is deemed to be the best choice among all the candidates. But syntactically, it's not an indirect object. More on dispatch rule interactions later.)

The comma still doesn't work if you go the other way and leave out the parens entirely, since


    doit $object, "a", "b", "c";

would always (in the absence of a prior sub declaration) be parsed as


    (doit $object:), "a", "b", "c";

So a print with both an indirect object and arguments has to look like one of these:


    print $*OUT: "Howdy, world!\n";
    print($*OUT: "Howdy, world!\n");
    print($*OUT): "Howdy, world!\n";

Note that the old Perl 5 form using curlies:


    print {some_hairy_expression()} "Howdy, world!\n";

should instead now be written with parentheses:


    print (some_hairy_expression()): "Howdy, world!\n";

though, in fact, in this case the parens are unnecessary:


    print some_hairy_expression(): "Howdy, world!\n";

You'd only need the parens if the invocant expression contained operators lower in precedence than comma (comma itself not being allowed). Basically, if it looks confusing to you, you can expect it to look confusing to the compiler, and to make the compiler look confused. But it's a feature for the compiler to look confused when it actually is confused. (In Perl 5 this was not always so.)

Note that the disambiguating colon associates with the closest method call, whether direct or indirect. So


    print $obj.meth: "Howdy, world!\n";

passes "Howdy, world!\n" to $obj.meth rather than to print. That's a case where you ought to have parenthesized the indirect object for clarity anyway:


    print ($obj.meth): "Howdy, world!\n";
Calling private methods

A private method does not participate in normal method dispatch. It is not listed in the class's public methods. The .can method does not see it. Calling it via normal dispatch raises a "no such method" exception. It is, in essence, invisible to the outside world. It does not hide a base class's method of the same name--even in the current class! It's fair to ask for warnings about name collisions, of course. But we're not following the C++ approach of making private methods visible but uncallable, because that would violate encapsulation, and in particular, Liskov substitutability. Instead, we separate the namespaces completely by distinguishing the public dot operator from the private dot-colon operator. That is:


    $mouth.say("Yes!")          # always calls public .say method
          .say("Yes!")          # unary form
    $brain.:think("No!")        # always calls private :think method
          .:think("No!")        # unary form

The inclusion of the colon prevents any kind of "virtual" behavior. Calling a private method is illegal except under two very specific conditions. You can call a private method :think on an object $brain only if:

  1. The class of $brain is explicitly declared, and the declared class is either the class definition that we are in or a class that has explicitly granted trust to our current class, and the declared class contains a private :think method. Or...
  2. The class of the $brain is not declared, and the current class contains a private :think method.

The upshot of these rules is that a private method call is essentially a subroutine call with a method-like syntax. But the private method we're going to call can be determined at compile time, just like a subroutine.

Class Methods

Class methods are called on the class as a whole rather than on any particular instance object of the class. They are distinguished from ordinary methods only by the declared type of the invocant. Since an implicit invocant would be typed as an object of the class and not as the class itself, the invocant declaration is not optional in a class method declaration if you wish to specify the type of the invocant. (Untyped explicit invocants are allowed to "squint", however.)

Class Invocant

To declare an ordinary class method, such as a constructor, you say something like:


    method new (Class $class: *@args) { ... }

Such a method may only be called with an invocant that "isa" Class, that is, an object of type Class, or derived from type Class.

Class|Object Invocant

It is possible to write a method that can be called with an invocant that is either a Class or an object of that current class. You can declare the method with a type junction:


    method new (Class|Dog $classorobj: *@args) { ... }

Or to be completely non-specific, you can leave out the type entirely:


    method new ($something: *@args) { ... }

That's not as dangerous as it looks, since almost by definition the dispatcher only calls methods that are consistent with the inheritance tree. You just can't say:


    method new (*@args) { ... }

which would be the equivalent of:


    method new (Dog $_: *@args) { ... }

Well, actually, you could say that, but it would require that you have an existing Dog-compatible object in order to create a new one. And that could present a little bootstrapping problem...

(Though it could certainly cure the boot chewing problem...)

But in fact, you'll rarely need to declare new method at all, because Perl supplies a default constructor to go with your class.

Submethods

Some methods are intended to be inherited by derived classes. Others are intended to be reimplemented in every class, or in every class that doesn't want the default method. We call these "submethods", because they work a little like subs, and a little like methods. (You can also read the "sub" with the meaning it has in words like "subhuman".)

Typically these are (sub)methods related to the details of construction and destruction of the object. So when you call a constructor, for instance, it ends up calling the BUILDALL initialization routine for the class, which ends up calling the BUILD submethod:


    submethod BUILD ($a, $b, $c) {
        $.a = $a;
        $.b = $b;
        $.c = $c;
    }

Since the submethod is doing things that make sense only in the context of the current class (such as initializing attributes), it makes no sense for BUILD to be inherited. Likewise DESTROY is also a submethod.

Why not just make them ordinary subs, then? Ordinary subs can't be called by method invocation, and we want to call these routines that way. Furthermore, if your base class does define an ordinary method named BUILD or DESTROY, it can serve as the default BUILD or DESTROY for all derived classes that don't declare their own submethods. (All public methods are virtual in Perl, but some are more virtual than others.)

You might be saying to yourself, "Wait, private methods aren't virtual. Why not just use a private method for this?" It's true that private methods aren't virtual, because they aren't in fact methods at all. They're just ordinary subroutines in disguise. They have nothing to do with inheritance. By contrast, submethods are all about presenting a unified inherited interface with the option of either inheriting or not inheriting the implementation of that interface, at the discretion of the class doing the implementing.

So the bottom line is that submethods allow you to override an inherited implementation for the current class without overriding the default implementation for other classes. But in any case, it's still using a public interface, called as an ordinary method call, from anywhere in your program that has an object of your type.

Or a class of your type. The default new constructor is an ordinary class method in class Object, so it's inherited by all classes that don't define their own new. But when you write your own new, you need to decide whether your constructor should be inherited or not. If so, that's good, and you should declare it as a method. But if not, you should declare it as a submethod so that derived classes don't try to use it erroneously instead of the default Object.new().

by Larry Wall

Editor's Note: this Apocalypse is out of date and remains here for historic reasons. See Synopsis 12 for the latest information.

Attributes

In Perl 6, "attributes" are what we call the instance variables of an object. (We used that word to mean something else in Perl 5--we're now calling those things "traits" or "properties".)

As with classes and methods, attribute declarations are apparently declarative. Underneath they actually call a method in the metaclass to install the new definition. The Perl 6 implementation of attributes is not based on a hash, but on something more like a symbol table. Attributes are stored in an opaque datatype rather like a struct in C, or an array in Perl 5--but you don't know that. The datatype is opaque in the sense that you shouldn't care how it's laid out in memory (unless you have to interface with an outside data structure--like a C struct). Do not confuse opacity with encapsulation. Encapsulation only hides the object's implementation from the outside world. But the object's structure is opaque even to the class that defines it.

One of the large benefits of this is that you can actually take a C or C++ data structure and wrap accessor methods around it without having to copy anything into a different data structure. This should speed up things like XML parsing.

Declaration of Attributes

In order to provide this opaque abstraction layer, attributes are not declared as a part of any other data structure. Instead, they are modeled on real variables, whose storage details are implicitly delegated to the scope in which they are declared. So attributes are declared as if they were normal variables, but with a strange scope and lifetime that is neither my nor our. (That scope is, of course, the current object, and the variable lives as long as the object lasts.) The class will implicitly store those attributes in a location distinct from any other class's attributes of the same name, including any base or derived class. To declare an attribute variable, declare it within the class definition as you would a my variable, but use the has declarator instead of my:


    class Dog is Mammal {
        has $.tail;
        has @.legs;
        ...
    }

The has declarator was chosen to remind people that attributes are in a "HASA" relationship to the object rather than an "ISA" relationship.

The other difference from normal variables is that attributes have a secondary sigil that indicates that they are associated with methods. When you declare an attribute like $.tail, you're also implicitly declaring an accessor method of the same name, only without the $ on the front. The dot is there to remind you that it's also a method call.

As with other declarations, you may add various traits to an attribute:


    has $.dogtag is rw;

If you want all your attributes to default to "rw", you can put the attribute on the class itself:


    class Coordinates is rw {
        has int $.x;
        has int $.y;
        has int $.z;
    }

Essentially, it's now a C-style struct, without having to introduce an ugly word like "struct" into the language. Take that, C++. :-)

You can also assign to a declaration:


    has $.master = "TheDamian";

Well, actually, this looks like an assignment, but it isn't. The effect of this is to establish a default; it is not executed at runtime. (Or more precisely, it runs when the class closure is executed by the metaclass, so it gets evaluated only once and the value is stored for later use by real instances. More below.)

Use of Attributes

The attribute behaves just like an ordinary variable within the class's instance methods. You can read and write the attributes just like ordinary variables. (It is, however, illegal to refer to an instance attribute variable (that is, a "has" variable) from within a class method. Class methods may only access class attributes, not instance attributes. See below.)

Bare attributes are automatically hidden from the outside world because their sigiled names cannot be seen outside the class's package. This is how Perl 6 enforces encapsulation. Outside the class the only way to talk about an attribute is through accessor methods. Since public methods are always virtual in Perl, this makes attribute access virtual outside the class. Always. (Unless you give the optimizer enough hints to optimize the class to "final". More on that later.)

In other words, only the class itself is allowed to know whether this attribute is, in fact, implemented by this class. The class may also choose to ignore that fact, and call the abstract interface, that is, the accessor method, in which case it might actually end up calling some derived class's overriding method, which might in turn call back to this class's accessor as a super method. (So in general, an accessor method should always refer to its actual variable name rather than the accessor method name to avoid infinite recursion.)

You may write your own accessor methods around the bare attributes, but if you don't, Perl will generate them for you based on the declaration of the attribute variable. The traits of the generated method correspond directly to the traits on the variable.

By default, a generated accessor is read-only (because by default any method is read-only). If you mark an attribute with the trait "is rw" though, the corresponding generated accessor will also be marked "is rw", meaning that it can be used as an lvalue.

In any event, even without "is rw" the attribute variable is always writable within the class itself (unless you apply the trait is constant to it).

As with private classes and methods, attributes are declared private using a colon on the front of their names. As with any private method, a private accessor is completely ignored outside its class (or, by extension, the classes trusted by this class).

To carry the separate namespace idea through, we incorporate the colon as the secondary sigil in declarations of private attributes:


    has $:x;

Then we can get rid of the verbose is private altogether. Well, it's still there as a trait, but the colon implies it, and is required anyway.) And we basically force people to document the private/public distinction every place they reference $:x instead of $.x, or $obj.:meth instead of $obj.meth.

We've seen secondary sigils before in earlier Apocalypses. In each case they're associated with a bizarre usage of some sort. So far we have:


    $*foo       # a truly global global (in every package)
    $?foo       # a regex-scoped variable
    $^foo       # an autodeclared parameter variable
    $.foo       # a public attribute
    $:foo       # a private attribute

As a form of the dreaded "Hungarian notation", secondary sigils are not introduced lightly. We define secondary sigils only where we deem instant recognizability to be crucial for readability. Just as you should never have to look at a variable and guess whether it's a true global, you should never have to look at a method and guess which variables are attributes and which ones are variables you just happen to be in the lexical scope of. Or which attributes are public and which are private. In Perl 6 it's always obvious--at the cost of a secondary sigil.

We do hereby solemnly swear to never, never, ever add tertiary sigils. You have been warned.

Default Values

You can set default values on attributes by pseudo-assignment to the attribute declaration:


    has Answer $.ans = 42;

These default values are associated as "build" traits of the attribute declaration object. When the BUILD submethod is initializing a new object, these prototype values are used for uninitialized attributes. The expression on the right is evaluated immediately at the point of declaration, but you can defer evaluation by passing a closure, which will automatically be evaluated at the actual initialization time. (Therefore, to initialize to a closure value, you have to put a closure in a closure.)

Here's the difference between those three approaches. Suppose you say:


    class Hitchhiker {
        my $defaultanswer = 0;
        has $.ans1 = $defaultanswer;
        has $.ans2 = { $defaultanswer };
        has $.ans3 = { { $defaultanswer } };
        $defaultanswer = 42;
        ...
    }

When the object is eventually constructed, $.ans1 will be initialized to 0, while $.ans2 will be initialized to 42. (That's because the closure binds $defaultanswer to the current variable, which still presumably has the value 42 by the time the BUILD routine initializes the new object, even though the lexical variable "$defaultanswer" has supposedly gone out of scope by the time the object is being constructed. That's just how closures work.)

And $.ans3 will be initialized not to 42, but to a closure that, if you ever call it, will also return 42. So since the accessor $obj.ans3() returns that closure, $obj.ans3().() will return 42.

The default value is actually stored under the "build" trait, so this:


    has $.x = calc($y);

is equivalent to this:


    has $.x is build( calc($y) );

and this:


    has $.x = { calc($y) };

is equivalent to either of these:


    has $.x is build( { calc($y) } );
    has $.x will build { calc($y) };

As with all closure-valued container traits, the container being declared (the $.x variable in this case) is passed as the topic to the closure (in addition to being the target that will be initialized with the result of the closure, because that's what build does). In addition to the magical topic, these build traits are also magically passed the same named arguments that are passed to the BUILD routine. So you could say


    has $.x = { calc($^y) };

to do a calculation based on the :y(582) parameter originally passed to the constructor. Or rather, that will be passed to the constructor someday when the object is eventually constructed. Remember we're really still at class construction time here.

As with other initializers, you can be more specific about the time at which the default value is constructed, as long as that time is earlier than class construction time:


    has $.x = BEGIN { calc() }
    has $.x = CHECK { calc() }
    has $.x = INIT  { calc() }
    has $.x = FIRST { calc() }
    has $.x = ENTER { calc() }

which are really just short for:


    has $.x is build( BEGIN { calc() } )
    has $.x is build( CHECK { calc() } )
    has $.x is build( INIT  { calc() } )
    has $.x is build( FIRST { calc() } )
    has $.x is build( ENTER { calc() } )

by Larry Wall

Editor's Note: this Apocalypse is out of date and remains here for historic reasons. See Synopsis 12 for the latest information.

Class Attributes

In general, class attributes are just package or lexical variables. If you define a package variable with a dot or colon, it autogenerates an accessor for you just as it does for an ordinary attribute:


    our $.count;        # generates a public read-only .count accessor
    our %:cache is rw;  # generates a private read-write .:cache accessor

The implicit invocant of these implicit accessors has a "squinting" type--it can either be the class or an object of the class. (Declare your own accessors if you have a philosophical reason for forcing the type one way or the other.)

The disadvantage of using "our" above is that both of these are accessible from outside the class via their package name (though the private one is Officially Ignored, and cannot be named simply by saying %MyClass:::cache because that syntax is specifically disallowed).

If on the other hand you declare your class variables lexically:


    my $.count;         # generates a read-only .count accessor
    my %:cache is rw;   # generates a read-write .:cache accessor

then the same pair of accessors are generated, but the variables themselves are visible only within the class block. If you reopen the class in another block, you can only see the accessors, not the bare variables. This is probably a feature.

Generally speaking, though, unless you want to provide public accessors for your class attributes, it's best to just declare them as ordinary variables (either my or state variables) to prevent confusion with instance attributes. It's a good policy not to declare any public accessors until you know you need them. They are, after all, part of your contract with the outside world, and the outside world has a way of holding you to your contracts.

Object Construction

The basic idea here is to remove the drudgery of creating objects. In addition we want object creation and cleanup to work right by default. In Perl 5 it's possible to make recursive construction and destruction work, but it's not the default, and it's not easy.

Perl 5 also confused the notions of constructor and initializer. A constructor should create a new object once, then call all the appropriate initializers in the inheritance tree without recreating the object. The initializer for a base class should be called before the initializer for any class derived from it.

The initializer for a class is always named BUILD. It's in uppercase because it's usually called automatically for you at construction time.

As with Perl 5, a constructor is only named "new" by convention, and you can write a constructor with any name you like. However, in Perl 6, if you do not supply a "new" method, a generic one will be provided (by inheritance from Object, as it happens).

The Default Constructor

The default new constructor looks like this:


    multi method new (Class $class: *%_) {
        return $class.bless(0, *%_);
    }

The arguments for the default constructor are always named arguments, hence the *%_ declaration to collect all those pairs and pass them on to bless.

You'll note also that bless is no longer a subroutine but a method call, so it's now impossible to omit the class specification. This makes it easier to inherit constructors. You can still bless any reference you could bless in Perl 5, but where you previously used a function to do that:



    # Perl 5 code...
    return bless( {attr => "hi"}, $class );


in Perl 6 you use a method call:


    # Perl 6 code...
    return $class.bless( {attr => "hi"} );

However, if what you pass as the first argument isn't a reference, bless is going to construct an opaque object and initialize it. In a sense, bless is the only real constructor in Perl 6. It first makes sure the data structure is created. If you don't supply a reference to bless, it calls CREATE to create the object. Then it calls BUILDALL to call all the initializers.

The signature of bless is something like:


    method bless ($class: $candidate, *%_)

The 0 candidate indicates the built-in opaque type. If you're really strange in the head, you can think of the "0" as standing for "0paque". Or it's the "zero" object, about which we know zip. Whatever tilts your windmill...

In any event, strings are reserved for other object layouts. We could conceivably have things like:


    return $class.bless("Cstruct", *%_);

So as it happens, 0 is short for the layout "P6opaque".

Any additional arguments to .bless are automatically passed on to CREATE and BUILDALL. But note that these must be named arguments. It could be argued that the only real purpose for writing a .new constructor in Perl 6 is to translate different positional argument signatures into a unified set of named arguments. Any other initialization common to all constructors should be done within BUILD.

Oh, the invocant of .bless is either a class or an object of the class, but if you use an object of the class, the contents of that object are not automatically used to prototype the new object. If you wish to do that, you have to do it explicitly by copying the attributes:


    $obj.bless(0, *%$obj)

(That is just a specific application of the general principle that if you treat any object like a hash, it will behave like one, to the extent that it can. That is, %$obj turns the attributes into key/value pairs, and passes those as arguments to initialize the new object. Note that %$obj includes the private attributes when used inside the class, but not outside.)

Just because .bless allows an object to be used for a class doesn't mean your new constructor has to do the same. Some folks have philosophical issues with mixing up classes and objects, and it's fine to disallow that on the constructor level. In fact, you'll note that the default .new above requires a Class as its invocant. Unless you override it, it doesn't allow an object for the constructor invocant. Go thou and don't likewise.

The default cloner

Another good reason not to overload .new to do cloning is that Perl will also supply a default .clone routine that works something like this:


    multi method clone ($proto: *%_) {
        return $proto.bless(0, *%_, *%$proto);
    }

Note the order of the two hash arguments to bless. This gives the supplied attribute values precedence over the copied attribute values, so that you can change some of the attributes en passant, if you like. That's because we're passing the two flattened hashes as arguments to .bless and Perl 6's named argument binding mechanism always picks the first argument that matches, not the last. This is opposite of what happens when you use the Perl 5 idiom:


    %newvals = (%_, %$proto);

In that case, the last value (the one in %$proto) would "win".

CREATE


    submethod CREATE ($self: *%args) {...}

CREATE is called when you don't want to use an existing data structure as the candidate for your object. In general you won't define CREATE because the default CREATE does all the heavy magic to bring an opaque object into existence. But if you don't want an opaque object, and you don't care to write all your constructors to create the data structure before calling .bless, you can define your own CREATE submethod, and it will override the standard one for all constructors in the class.

BUILDALL


    submethod BUILDALL ($self: *%args) {...}

After the data structure is created, it must be populated by each of the participating classes (and roles) in the proper order. The BUILDALL method is called upon to do this. The default BUILDALL is usually correct, so you don't generally have to override it. In essence, it delegates the initialization of parent classes to the BUILDALL of the parent classes, and then it calls BUILD on the current class. In this way the pieces of the object are assembled in the correct order, from least derived to most derived.

For each class BUILDALL calls on, if the arguments contain a pair whose key is that class name, it passes the value of the pair as its argument to that class's BUILDALL. Otherwise it passes the entire list. (There's not much ambiguity there--most classes and roles will start with upper case, while most attribute names start with lower case.)

BUILD


    submethod BUILD ($self: *%args) {...}

That is the generic signature of BUILD from the viewpoint of the caller, but the typical BUILD routine declares explicit parameters named after the attributes:


    submethod BUILD (+$tail, +@legs, *%extraargs) {
        $.tail = $tail;
        @:legs = @legs;
        ...
    }

That occurs so frequently that there's a shorthand available in the signature declaration. You can put the attributes (distinguished by those secondary sigils, you'll recall) right into the signature. The following means essentially the same thing, without repeating the names:


    submethod BUILD (+$.tail, +@:legs, *%extraargs) {...}

It's actually unnecessary to declare the *%extraargs parameter. If you leave it out, it will default to *%_ (but only on methods and submethods--see the section on Interface Consistency later).

You may use this special syntax only for instance attributes, not class attributes. Class attributes should generally not be reinitialized every time you make a new object, after all.

If you do not declare a BUILD routine, a default routine will be supplied that initializes any attributes whose names correspond to the keys of the argument pairs passed to it, and leaves the other attributes to default to whatever the class supplied as the default, or undef otherwise.

In any event, the assignment of default attribute values happens automatically. For any attribute that is not otherwise initialized, the attribute declaration's "build" property is evaluated and the resulting value copied in to the newly created attribute slot. This happens logically at the end of the BUILD block, so we avoid running initialization closures unnecessarily. This implicit initialization is based not on whether the attribute is undefined, but on whether it was initialized earlier in BUILD. (Otherwise we could never explicitly create an attribute with an undefined value.)

by Larry Wall

Editor's Note: this Apocalypse is out of date and remains here for historic reasons. See Synopsis 12 for the latest information.

Eliminating Redundancy in Constructor Calls

If you say:


    my Dog $spot = Dog.new(...)

you have to repeat the type. That's not a big deal for a small typename, but sometime typenames are a lot longer. Plus you'd like to get rid of the redundancy, just because it's, like, redundant. So there's a variant on the dot operator that looks a lot like a dot assignment operator:


    my Dog $spot .= new(...)

It doesn't really quite fit the assignment operator rule though. If it did, it'd have to mean:


    my Dog $spot = $spot.new(...)

which doesn't quite work, because $spot is undefined. What probably happens is that the my cheats and puts a version of undef in there that knows it should dispatch to the Dog class if you call .self:new() on it. Anyway, we'll make it work one way or another, so that it becomes the equivalent of:


    my Dog $spot = Dog.new(...)

The alternative is to go the C++ route and make new a reserved word. We're just not going to do that.

Note that an attribute declaration of the form


    has Tail $wagger .= new(...)

might not do what you want done when you want it done, if what you want done is to create a new Dog object each time an object is built. For that you'd have to say:


    has Tail $wagger = { .new(...) }

or equivalently,


    has Tail $wagger will build { .new(...) }

But leaving aside such timing issues, you should generally think of the .= operator more as a variant on . than a variant on +=. It can, for instance, turn any non-mutating method call into a mutating method:


    @array.=sort;       # sort @array in place
    .=lc;               # lowercase $_ in place

This presumes, of course, that the method's invocant and return value are of compatible types. Some classes will wish to define special in-place mutators. The syntax for that is:


    method self:sort (Array @a is rw) {...}

It is illegal to use return from such a routine, since the invocant is automatically returned. If you do not declare the invocant, the default invocant is automatically considered "rw". If you do not supply a mutating version, one is autogenerated for you based on the corresponding copy operator.

Object Deconstruction

Object destruction is no longer guaranteed to be "timely" in Perl 6. It happens when the garbage collector gets around to it. (Though there will be ways to emulate Perl 5 end-of-scope cleanup.)

As with object creation, object destruction is recursive. Unlike creation, it must proceed in the opposite order.

DESTROYALL

The DESTROYALL routine is the counterpart to the BUILDALL routine. Similarly, the default definition is normally sufficient for the needs of most classes. DESTROYALL first calls DESTROY on the current class, and then delegates to the DESTROYALL of any parent classes. In this way the pieces of the object are disassembled in the correct order, from most derived to least derived.

DESTROY

As with Perl 5, all the memory deallocation is done for you, so you really only need to define DESTROY if you have to release external resources such as files.

Since DESTROY is the opposite of BUILD, if any attribute declaration has a "destroy" property, that property (presumably a closure) is evaluated before the main block of DESTROY. This happens even if you don't declare a DESTROY.

(The "build" and "destroy" traits are the only way for roles to let their preferences be made known at BUILD and DESTROY time. It follows that any role that does not define an attribute cannot participate in building and destroying except by defining a method that BUILD or DESTROY might call. In other words, stateless roles aren't allowed to muck around with the object's state. This is construed as a feature.)

Dispatch Mechanisms

Perl 6 supports both single dispatch (traditional OO) and multiple dispatch (also known as "multimethod dispatch", but we try to avoid that term).

Single Dispatch

Single dispatch looks up which method to run solely on the basis of the type of the first argument, the invocant. A single-dispatch call distinguishes the invocant syntactically (unlike a multiple-dispatch call, which looks like a subroutine call, or even an operator.)

Basically, anything can be an invocant as long as it fills the Dispatch role, which provides a .dispatcher method. This includes ordinary objects, class objects, and (in some cases) even varieties of undef that happen to know what class of thing they aren't (yet).

Simple single dispatch is specified with the dot operator, or its indirect object equivalent:


    $object.meth(@args)   # always calls public .meth
           .meth(@args)   # unary form
    meth $object: @args   # indirect object form

There are variants on the dot form indicated by the character after the dot. (None of these variants allows indirect object syntax.) The private dispatcher only ever dispatches to the current class or its proxies, so it's really more like a subroutine call in disguise:


    $object.:meth(@args)  # always calls private :meth
           .:meth(@args)  # unary form

It is an error to use .: unless there is a correspondingly named "colon" method in the appropriate class, just as it is an error to use . when no method can be found of that name. Unlike the .: operator, which can have only one candidate method, the . operator potentially generates a list of candidates, and allows methods in that candidate list to defer to subsequent methods in other classes until a candidate has been found that is willing to handle the dispatch.

In addition to the .: and .= operators, there are three other dot variants that can be used if it's not known how many methods are willing to handle the dispatch:


    $object.?meth(@args)  # calls method if there is one
           .?meth(@args)  # unary form
    $object.*meth(@args)  # calls all methods (0 or more)
           .*meth(@args)  # unary form
    $object.+meth(@args)  # calls all methods (1 or more)
           .+meth(@args)  # unary form

The .* and .+ versions are generally only useful for calling submethods, or methods that are otherwise expected to work like submethods. They return a list of all the successful return values. The .? operator either returns the one successful result, or undef if no appropriate method is found. Like the corresponding regex modifiers, ? means "0 or 1", while * means "0 or more", and + means "1 or more". Ordinary . means "exactly one". Here are some sample implementations, though of course these are probably implemented in C for maximum efficiency:


    # Implements . (or .? if :maybe is set).
    sub CALLONE ($obj, $methname, +$maybe, *%opt, *@args) {
        my $startclass = $obj.dispatcher() // fail "No dispatcher: $obj";
      METHOD:
        for WALKMETH($startclass, :method($methname), %opt) -> &meth {
            return meth($obj, @args);
        }
        fail qq(Can't locate method "$methname" via class "$startclass")
            unless $maybe;
        return;
    }

With this dispatcher you can continue by saying "next METHOD". This allows methods to "failover" to other methods if they choose not to handle the request themselves.


    # Implements .+ (or .* if :maybe is set).
    #   Add :force to redispatch in every class
    sub CALLALL ($obj, $methname, +$maybe, +$force, *%opt, *@args) {
        my $startclass = $obj.dispatcher() // fail "No dispatcher: $obj";
        my @results = gather {
            if $force {
              METHOD:
                for WALKCLASS($startclass, %opt) -> $class {
                    take $obj.::($class)::$methname(*@args) # redispatch
                }
            }
            else {
              METHOD:
                for WALKMETH($startclass, :method($methname), %opt) -> &meth {
                    take meth($obj,*@args);
                }
            }
        }
        return @results if @results or $maybe;
        fail qq(Can't locate method "$methname" via class "$startclass");
    }

This one you can quit early by saying "last METHOD". Notice that both of these dispatchers cheat by calling a method as if it were a sub. You may only do that by taking a reference to the method, and calling it as a subroutine, passing the object as the first argument. This is the only way to call a virtual method non-virtually in Perl. If you try to call a method directly as a subroutine, Perl will ignore the method, look for a subroutine of that name elsewhere, probably not find it, and complain bitterly. (Or find the wrong subroutine, and execute it, after which you will complain bitterly.)

We snuck in an example the new gather/take construct. It is still somewhat conjectural.

Calling Superclasses, and Not-So-Superclasses

Perl 5 supplies a pseudoclass, SUPER::, that redirects dispatch to a parent class's method. That's often the wrong thing to do, though, in part because under MI you may have more than one parent class, and also because you might have sibling classes that also need to have the given method triggered. Even if SUPER is smart enough to visit multiple parent classes, and even if all your classes cooperate and call SUPER at the right time, the depth first order of visitation might be the wrong order, especially under diamond inheritance. Still, if you know that your parent classes use SUPER, or you're calling into a language with SUPER semantics (such as Perl 5) then you should probably use SUPER semantics too, or you'll end up calling your parent's parents in duplicate. However, since use of SUPER is slightly discouraged, we Huffman code it a bit longer in Perl 6. Remember the *%opt parameters to the dispatchers above? That comes in as a parameterized pseudoclass called WALK.


    $obj.*WALK[:super]::method(@args)

That limits the call to only those immediate super classes that define the method. Note the star in the example. If you really want the Perl 5 semantics, leave the star out, and you'll only get the first existing parent method of that name. (Why you'd want that is beyond me.)

Actually, we'll probably still allow SUPER:: as a shorthand for WALK[:super]::, since people will just hack it in anyway if we don't provide it...

If you think about it, every ordinary dispatch has an implicit WALK modifier on the front that just happens to default to WALK[:canonical]. That is, the dispatcher looks for methods in the canonical order. But you could say WALK[:depth] to get Perl 5's order, or you could say WALK[:descendant] to get an order approximating the order of construction, or WALK[:ascendant] to get an order approximating the order of destruction. You could say WALK[:omit(SomeClass)] to call all classes not equivalent to or derived from SomeClass. For instance, to call all super classes, and not just your immediate parents, you could say WALK[:omit(::_)] to skip the current lexical class or anything derived from it.

But again, that's not usually the right thing to do. If your base classes are all willing to cooperate, it's much better to simply call


    $obj.method(@args)

and then let each of the implementations of the method defer to the next one when they're done with their part of it. If any method says "next METHOD", it automatically iterates the loop of the dispatcher and finds the next method to dispatch to, even if that method comes from a sibling class rather than a parent class. The next method is called with the same arguments as originally supplied.

That presupposes that the entire set of methods knows to call "next" appropriately. This is not always the case. In fact, if they don't all call next, it's likely that none of them does. And maybe just knowing whether or not they do is considered a violation of encapsulation. In any case, if you still want to call all the methods without their active cooperation, then use the star form:


    $obj.*method(@args)

Then the various methods don't have to do anything to call the next method--it happens automatically by default. In this case a method has to do something special if it wants to stop the dispatch. Naturally, that something is to call "last METHOD", which terminates the dispatch loop early.

Now, sometimes you want to call the next method, but you want to change the arguments so that the next method doesn't get the original argument list. This is done with deep magic. If you use the call keyword in an ordinary (nonwrapper) method, it steals the rest of the dispatch list from the outer loop and redispatches to the next method with the new arguments:


    @retvals = call(@newargs)
    return @retvals;

And unlike with "next METHOD", control returns to this method following the call. It returns the results of the subsequent method calls, which you should return so that your outer dispatcher can add them to the return values it already gathered.

Note that "next METHOD" and "last METHOD" can typically be spelt "next" and "last" unless they are in an inner loop.

by Larry Wall

Editor's Note: this Apocalypse is out of date and remains here for historic reasons. See Synopsis 12 for the latest information.

Parallel Dispatch

By default the various dot operators call a method on a single object, even if it ends up calling multiple methods for that object. Since a method call is essentially a unary postfix operator, however, you can use it as a hyper operator on a list of objects:


    @object».meth(@args)        # Call one for each or fail
    @object».?meth(@args)       # Call one for each if available
    @object».*meth(@args)       # Call all available for each
    @object».+meth(@args)       # Call one or more for each

Note that with the last two, if a method uses "last METHOD", it doesn't bomb out of the "hyper" loop, but just goes on to the next entry. One can always bomb out of the hyperloop with a real exception, of course. And maybe with "last HYPER", depending on how hyper's implicit iteration is implemented.

If you want to use an array for serial rather than parallel method calling, see Delegation, which lets you set up cascading handlers.

WALKCLASS and WALKMETH Caching

WALKCLASS generates a list of matching classes. WALKMETH generates a list of method references from matching classes.

The WALKCLASS and WALKMETH routines used in the sample dispatch code need to cache their results so that every dispatch doesn't have to traverse the inheritance tree again, but just consult the preconstructed list in order. However, if there are changes to any of the classes involved, then someone needs to call the appropriate cache clear method to make sure that the inheritance is recalculated.

WALKCLASS/WALKMETH options include some that specify ordering:


    :canonical      # canonical dispatch order
    :ascendant      # most-derived first, like destruction order
    :descendant     # least-derived first, like construction order
    :preorder       # like Perl 5 dispatch
    :breadth        # like multimethod dispatch

and some that specify selection criteria:


    :super              # only immediate parent classes
    :method(Str)        # only classes containing method declaration
    :omit(Selector)     # only classes that don't match selector
    :include(Selector)  # only classes that match selector

Note that :method(Str) selects classes that merely have methods declared, not necessarily defined. A declaration without a definition probably implies that they intend to autoload a definition, so we should call the stub anyway. In fact, Perl 6 differentiates an AUTOMETHDEF from AUTOLOAD. AUTOLOAD works as it does in Perl 5. AUTOMETHDEF is never called unless there is already a declaration of the stub (or equivalently, AUTOMETH faked a stub.)

It would be possible to just define everything in terms of WALKCLASS, but that would imply looking up each method name twice, once inside WALKCLASS to see if the method exists in the current class, and once again outside in order to call it. Even if WALKCLASS caches the cache list, it wouldn't cache the derived method list, so it's better to have a separate cache for that, controlled by WALKMETH, since that's the common case and has to be fast.

(Again, this is all abstract, and is probably implemented in gloriously grungy C code. Nevertheless, you can probably call WALKCLASS and WALKMETH yourself if you feel like writing your own dispatcher.)

Multiple Dispatch

Multiple dispatch is based on the notion that methods often mediate the relationships of multiple objects of diverse types, and therefore the first object in the argument list should not be privileged over other objects in the argument list when it comes to selecting which method to run. In this view, methods aren't subservient to a particular class, but are independent agents. A set of independent-minded, identically named methods use the class hierarchy to do pattern matching on the argument list and decide among themselves which method can best handle the given set of arguments.

The Perl approach is, of course, that sometimes you want to distinguish the first invocant, and sometimes you don't. The interaction of these two approaches gets, um, interesting. But the basic notion is to let the caller specify which approach is expected, and then, where it makes sense, fall back on the other approach when the first one fails. Underlying all this is the Principle of Least Surprise. Do not confuse this with the Principle of Zero Surprise, which usually means you've just swept the real surprises under some else's carpet. (There's a certain amount of surprise you can't go below--the Heisenberg Uncertainty Principle applies to software too.)

With traditional multimethods, all methods live in the same global namespace. Perl 6 takes a different approach--we still keep all the traditional Perl namespaces (lexical, package, global) and we still search for names the same way (outward through the lexical scopes, then the current package, then the global * namespace; or upward in the class hierarchy). Then we simply claim that, under multiple dispatch, the "long name" of any multi routine includes its signature, and that visibility is based on the long name. So an inner or derived multi only hides an outer or base multi of the same name and the same signature. (Routines not declared "multi" still hide everything in the traditional fashion.)

To put it another way, the multiple dispatch always works when both the caller and the callee agree that that's how it should work. (And in some cases it also works when it ought to work, even if they don't agree--sort of a "common law" multimethod, as it were...)

Declaration of Multiple Dispatch Routines

A callee agrees to the multiple dispatch "contract" by including the word "multi" in the declaration of the routine in question. It essentially says, "Ordinarily this would be a unique name, but it's okay to have duplicates of this name (the short name) that are differentiated by signatures (the long name)."

Looking at it from the other end, leaving the "multi" out says "I am a perfect match for any signature--don't bother looking any further outward or upward." In other words, the standard non-multi semantics.

You may not declare a multi in the same scope as a non-multi. However, as long as they are in different scopes, you can have a single non-multi inside a set of multis, or a set of multis inside a single non-multi. You can even have a set of multis inside a non-multi inside a set of multis. Indeed, this is how you hide all the outer multis so that only the inner multi's long names are considered. (And if no long name matches, you get the intermediate non-multi as a kind of backstop.) The same policy applies to both nested lexical scopes and derived subclasses.

Actually, up till now we've been oversimplifying the concept of "long name" slightly. The long name includes only that part of the signature up to the first colon. If there is no colon, then the entire signature is part of the long name. (You can have more colons, in which case the additional arguments function as tie breakers if the original set of long names is insufficient to prevent a tie.)

So sometimes we'll probably slip and say "signature" when we mean "long nam