Sign In/My Account | View Cart  
advertisement


Listen Print

Apocalypse 6
by Larry Wall | Pages: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16

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

In Perl 6, the type of the variable is just one of the traits of the variable, so if you want to do the equivalent of a tie to the Box class, you say something like:


    my Cat $felix is Box;

That declares your intent to store a Cat value into a Box variable. (Whether the cat will then dead or alive (or dead|alive) depends on the definition of the Box class, and whether the Box object's side effects extend to the Cat value stored in it.)

But by default:


    my Cat $felix;

just means something like:


    my Cat $felix is Scalar;

Likewise, if you say:


    my Cat @litter;

it's like saying:


    my Cat @litter is Array;

That is, @litter is an ordinary array of scalar values that happen to be references to Cats. In the abstract, @litter is a function that maps integers to cats.

Likewise,


    my Cat %pet;

is like:


    my Cat %pet is Hash;

You can think of the %pet hash as a function that maps cat names (strings) to cats. Of course, that's an oversimplification--for both arrays and hashes, subscripting is not the only operation. But it's the fundamental operation, so the declared type of the returned value reflects the return value of such a subscripted call.

Actually, it's not necessarily the return type. It's merely a type that is consistent with the returned type. It would be better to declare:


    my Animal %pet;

and then you could return a Cat or a Dog or a Sponge, presuming all those are derived from Animal. You'd have to generalize it a bit further if you want to store your pet Rock. In the limit, you can just leave the type out. When you say:


    my %pet;

you're really just saying:


    my Object %pet is Hash;

...except that you're not. We have to push it further than that, because we have to handle more complicated structures as well. When you say:


    my Cat @litter is Array;

it's really shorthand for:


    my @litter is Array of Cat;

That is, "Cat" is really a funny parameter that says what kind of Array you have. If you like, you could even write it like this:


    my @litter is Array(returns => Cat)

Likewise you might write:


    my %pet is Hash(keytype => Str, returns => Cat)

and specify the key type of the hash. The "of" keyword is just syntactic sugar for specifying the return type of the previous storage class. So we could have


    my %pet is Hash of Array of Array of Hash of Array of Cat;

which might really mean:


    my %pet is Hash(keytype => Str,
                    returns => Array(
                        returns => Array(
                            returns => Hash(
                                keytype => Str,
                                returns => Array(
                                    returns => Cat)))))

or some such.

I suppose you could also write that as:


    my Array of Array of Hash of Array of Cat %pet;

but for linguistic reasons it's probably better to keep the variable name near the left and put the long, heavy phrases to the right. (People tend to prefer to say the short parts of their sentences before the long parts--linguists call this the "end-weight" problem.) The Hash is implied by the %pet, so you could leave out the "is" part and just say:


    my %pet of Array of Array of Hash of Array of Cat;

Another possibility is:


    my Cat %pet is Hash of Array of Array of Hash of Array;

That one reads kinda funny if you leave out the "is Hash", though. Nevertheless, it says that we have this funny data structure that has multiple parameters that you can view as a funny function returning Cat. In fact, "returns" is a synonym for "of". This is also legal:


    my @litter returns Cat;

But the "returns" keyword is mostly for use by functions:


    my Cat sub find_cat($name) {...}

is the same as:


    my sub find_cat($name) returns Cat {...}

This is more important for things like closures that have no "my" on the front:


    $closure = sub ($name) returns Cat {...}

Though for the closure case, it's possible we could define some kind of non-my article to introduce a type unambiguously:


    $closure = a Camel sub ($name) {...}
    $closure = an Aardvark sub () {...}

Presumably "a" or "an" is short for "anonymous". Which is more or less what the indefinite article means in English.

However, we need returns anyway in cases where the return value is complicated, so that you'd rather list it later (for end-weight reasons):


    my sub next_prisoner() returns (Nationality, Name, Rank, SerialNo) {...}

Note that the return type is a signature much like the parameter types, though of course there are no formal parameter names on a return value. (Though there could be, I suppose.) We're calling such nameless signatures "siglets".

Stub declarations

When you declare a subroutine, it can change how the rest of the current file (or string) is compiled. So there is some pressure to put subroutine declarations early. On the other hand, there are good reasons for putting subroutine definitions later in the file too, particularly when you have mutually recursive subroutines. Beyond that, the definition might not even be supplied until run time if you use some kind of autoloading mechanism. (We'll discuss autoloading in Apocalypse 10, Packages.) Perl 5 has long supported the notion of "forward" declarations or "stubs" via a syntax that looks like this:


    sub optimal;

Perl 6 also supports stubbing, but instead you write it like this:


    sub optimal {...}

That is, the stub is distinguished not by leaving the body of the function out, but by supplying a body that explicitly calls the "..." operator (known affectionately as the "yada, yada, yada" operator). This operator emits a warning if you actually try to execute it. (It can also be made to pitch an exception.) There is no warning for redefining a {...} body.

We're moving away from the semicolon syntax in order to be consistent with the distinction made by other declarations:


    package Fee;        # scope extends to end of file
    package Fee { ... } # scope extends over block

    module Fie;         # scope extends to end of file
    module Fie { ... }  # scope extends over block

    class Foe;          # scope extends to end of file
    class Foe { ... }   # scope extends over block

To be consistent, a declaration like:


    sub foo;

would therefore extend to the end of the file. But that would be confusing for historical reasons, so we disallow it instead, and you have to say:


    sub foo {...}

Pages: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16

Next Pagearrow