Sign In/My Account | View Cart  
advertisement


Listen Print

This week on Perl 6, week ending 2003-04-20
by Piers Cawley | Pages: 1, 2, 3

Types...

Well, that's 100 or so messages accounted for. Which leaves another 173 messages remaining all of which concern types. The problem as I see it is that different people seem to understand different things from the word type, and there's a lot of people talking at cross purposes as well as a fair amount of axe grinding going on.

Now, I could just punt and write something like "Everyone except Leon Brocard talked for ages about types. Here are the links to those threads" which would at least has the virtue of getting the god awful running joke out of the way, but that would smack of cheating. So, what I'm going to do is to only cheat slightly. At the bottom of this section you'll find links to all the threads that discussed types this week. However, before that I'll try give you a (biased) overview of the issues involved and the areas of confusion.

An illustrative quotation from Lewis Carroll

"The name of the song is called 'Haddocks' Eyes.'" [said the White Knight.]

"Oh, that's the name of the song, is it?" Alice said, trying to feel interested.

"No, you don't understand," the Knight said, looking a little vexed. "That's what the name is called. The name really is 'The Aged, Aged Man.'"

"Then I ought to have said 'That's what the song is called'?" Alice corrected herself.

"No you oughtn't: that's another thing. The song is called 'Ways and Means' but that's only what it's called, you know!"

"Well, what is the song then?" said Alice, who was by this time completely bewildered.

"I was coming to that," the Knight said. "The song really is 'A-sitting On a Gate': and the tune's my own invention."

-- From Alice Through The Looking Glass, by Lewis Carroll

Two types of type

Perl 6 draws an important distinction between 'variable type' and 'value type'. A variable is a binding between a name and a container. The variable type is the type of the container associated with the variable's name. A variable's 'value type' is the expected type of the value stored in the variable's container. As far as I can tell, Perl is weirder than the average programming language in this respect in that it allows the programmer to specify both sorts of type. In C for instance, a value doesn't know its own type, it's just an area of memory that is interpreted according to the type of the variable that it is accessed via (or according to the type it is cast into). Meanwhile, in lisp like languages, 'variables' are simply keys in a symbol table, and the values in that symbol table are untyped pointers to values which know their own type.

Perl 6's symbol tables are rather more like Lisp symbol tables than C's, with the added wrinkle that the symbol table values are rather more sophisticated containers than simple generic pointers. This complexity arises for a couple of reasons:

Tied variables.
Instead of storing a variable's value in one of the core container types (Array, Hash, Scalar), it can be useful to use a custom container type to allow for 'magical' behaviour:
    my $FTSE is ShareIndex('FTSE');
    print "$FTSE";
    # FTSE 100 Index: 3916.70 (+27.50/+0.7%) at 2003042216:40
Context
Context is really important to Perl. If you look at an array variable in a numeric context, then you get the number of items in the array; in list context, a list of all the items in the array; in a scalar context, a pointer to the array. This context dependent behaviour is best handled by the container object, possibly with the assistance of the contained object, but not always.

Scalars turn out to be one of the more remarkable types of Perl containers. At their simplest they can be thought of as a container which can hold at most one 'atomic' thing. Perl 5 scalars have three(?) slots for Number, String and Reference values (On IRC, Dan tells me that Perl 6 scalars will probably have slots for String, Float, Integer, Boolean and Reference values). These different 'scalar value types' can, with certain restrictions be treated without regard to their 'actual' type: A Number in a string context will give a sensible string representation, a string in a number context will give an appropriate numeric value, but not every possible scalar value type can be sensibly viewed as any other type; if you try and use a number in a reference context, you're going to get an error for instance. For added fun, it's perfectly possible for a scalar variable to contain both a Number value and a String value (In Perl 5, Scalar::Util provides a nice interface to this preexisting capability. On IRC, Dan suggests that the Perl 6ish way of doing this will probably be my $i = 4 but "Bibble!";).

What are value type declarations for?

Some people see value type declarations as being important for programmer safety. They want to see a situation where:

    my Number $foo = some_function_returning_a_string();

or

    sub a_func (Number $param) { ... }

    a_func("A string");

will throw exceptions, preferably at compile time.

Others want to see those same code fragments coerce any values assigned to them into the appropriate types (possibly with a warning) and see value type declarations simply as a way of letting the compiler do automatic optimization of code (if you have declared that a given variable will only contain, say, a number, you can (at least) get rid of a layer of indirection in accessing that value).

Others don't really care one way or the other about whether or not to coerce, they just want to use value types in setting up multimethods.

Still others don't really like the idea of declaring types at all, but do see value in ML like type inference for programmer safety reasons...

Others want to let the programmer choose, and worry about how to implement something which will let that happen. I'm a 'let the programmer choose, and the compiler optimize what it can' kind of guy.

Are types the same as objects?

If types are the same as objects, do they all inherit from a common base class? If they do, what does the hierarchy look like? What about interfaces? Do they need to be explicitly declared or can they be inferred. If they can be inferred, what about the problem of:

    class Tree {
        method feed {...}
        method grow {...}
        method bark {...}
        ...
    }

    interface Canine {
        method feed {...}
        method grow {...}
        method bark {...}
    }

    class Borzoi {
        method feed {...}
        method grow {...}
        method bark {...}
    }

    ...

    multi treat($vet, Canine $critter ) {...}
    
    treat($some_vet, Tree.new); # Should this fail?

Arrghh!!! Make the hurting stop!

However, I don't care what Dan says, I want every type to have an associated class, and I want them all to inherit from some sort of common base class (at least conceptually, and, if I'm prepared to take the performance hit and jump through the hoops, actually. Sometimes you need to override Scalar's behaviour (or whatever)) but I don't think the inheritance trees that have been bandied about so far even come close to expressing the semantics we need. Expect a longish post to Perl 6 language on this at some point. Probably with (more or less) pseudo code.

Another distinction to think about

OO theory talks about value objects and reference objects. (I'm using 'object' here to try and get come conceptual distance from 'value type'). Here's an abstract example of what I mean

    my $a = new ValueObject: value => 10;
    my $b = $a;

    $b.set_value(20);
    
    print "$a $b"; # 10 20

    my $c = new ReferenceObject: value => 10;
    my $d = $c;

    $c.set_value(20)

    print "$c $d"; # 20 20

Just when you thought you understood value types...

Along come compound value types to mess with your head. Assuming a strict interpretation of value type declarations (assigning the the 'wrong' type to a variable throws an error), consider the following:

    my @a of Int = (1, 2, 3);
    my @b = @a;
    my @c of Str;

What happens to each of the following? If it's an error does it happen at runtime or compile time?

    @c = @a;
    @c = @b;

    push @a, "String";
    push @b, "String";

Are you sure about those? Now, what happens if you start with:

    my @a of Int = (1 .. Inf);
    my @b = @a;
    my @c of Str;

And there's more thorny problems where they came from.

Those thread links

http://groups.google.com/groups -- Types of literals

http://groups.google.com/groups -- Do we really need the dual type system

http://groups.google.com/groups -- User defined hierarchical types

http://groups.google.com/groups -- Mind the difference between value types and reference types

http://groups.google.com/groups -- Static typing with Interfaces

http://groups.google.com/groups -- Michael Lazzaro's superb summary of how containers and values interact. Not sure it's the whole story though...

Acknowledgements, Announcements and Apologies

Sorry it's late. I blame the perl6-language people. It has nothing whatsoever to do with weekend spent in Wales and a Bank Holiday Monday spent at an Easter egg hunt and barbecue at my aunt's.

This has been one of the harder Perl 6 summaries to write, mostly because the language list has been dealing with a complicated subject and finding lots of interesting corners and ambiguities. Many thanks to Michael Lazzaro for his careful summation of his understanding of how things work which certainly clarified my thinking, to Stéphane Payrard for his sanity check of the types summary and to Dan Sugalski for a few answers on IRC about Scalar behaviour.

If you've appreciated this summary, please consider one or more of the following options: