This week on Perl 6, week ending 2003-04-20

By Piers Cawley on April 20, 2003 12:00 AM

You know how it is,
you go away for a lovely weekend folk festival in Wales,
you have a really good,
relaxed time,
singing yourself hoarse and generally forgetting all about technology before coming home to email from the perl.com editor asking if he could have the summary about half an hour ago,
and then you skim through the lists and find nearly 300 messages unread?
You do?
I thought it was just me.
So,
having utterly failed (by virtue of being elsewhere) to get a summary written by Monday,
I'm currently shooting for 'getting it written'.
Welcome to this week's Perl 6 summary; all the fun of the Perl 6 lists with none of the tedious 'reading every message'.

Let's see if I can't ease myself back into the Perl 6 vibe by summarizing the still rather quiet perl6-internals list first...

Steve Fink has been busy committing (in the CVS rather than the culpability sense) Mattia Barbon's patches to get Parrot building happily in a Win32 environment.
If you have such an environment,
now would probably be a good time to grab the latest Parrot from CVS and see if it builds for you.
I'm sure the list would be grateful to hear of your experience,
good or bad.

After seemingly weeks in the wilderness with very little feedback,
Alberto Simões finally got some comments on (and thanks for) his latest PMC doc patches from Steve Fink and Brent Dax.
The docs haven't made it into the distribution yet though,
but it can only be a matter of time.

Mattia Barbon wanted to know if it would eventually become possible to create PMCs with additional data members.
Dan says not; PMCs are allocated from arenas which apparently means they need to be the same size (variable sized PMCs would mean adding complexity to the garbage collector,
which is already complicated enough thanks very much...)

Luke Palmer wondered what the Right Way was to allocate dynamic memory that wouldn't be needed beyond a function invocation.
The answer,
of course,
was 'use Parrot memory management and let Garbage Collection work its shiny magic'.
Toward the end of the thread Dan let on that Parrots Garbage Collector is 'always going to be walking the system stack' so there was no need to worry about anchoring the newly allocated buffer to the root set for the duration of the function invocation,
which seems to be a new commitment.
Both Dan and Steve Fink observed that the memory documentation could use updating to clarify best practice for everyone.
Volunteers?

Alberto Simões asked how deeply the clone operator worked.
According to Leopold Tötsch it's a deep,
recursive clone,
which he noted makes for interesting times when dealing with self referencing structures (Dan reckoned that it shouldn't be too bad if you take advantage of the GC system's graph traversal smarts...).
Luke Palmer wondered why the default was a deep copy as,
he claimed,
deep copies were seldom needed.
He wondered how to make a shallow copy.
Leo suggested extending clone with an extra parameter to specify deep or shallow copying.
Dan said that it is the way it is because he said so,
and that one would make a shallow copy with assign.

David Robins wondered whether Parrot's memory allocation system would cope with sharing memory between processes and found some messages in the archive that seemed to imply that 'it will cope eventually'.
He wondered how it would cope.
Warnock's Dilemma applies...

Kurt Stephens announced that he had a partially written 'conservative,
non-copying "treadmill"' GC system that could work in real time without stopping the world.
He wondered if it could be useful for Parrot.
No comments so far...

K Stol wondered how to handle a variable number of function arguments in IMC code.
Dan remarked that it was covered by the Parrot calling conventions (presumably IMC code doesn't do the dfull Parrot calling conventions though).
Leo Tötsch suggested making sure that the last thing pushed onto the argument stack was the number of arguments,
and Will Coleda suggested passing a single PMC like a PerlArray...

If I were asked to summarize this week's traffic on perl6-language with one word,
that word would be 'Types'.
It turns out that thinking about types,
and how they should behave in Perl 6,
is hard.
I don't envy Damian the writing of the next Exegesis,
that's for sure.

Instead of presenting the threads in roughly chronological order this week I'm going to deal with the none type related threads first and then attempt to sketch the current issues with types without quite so much reference to individual threads.
Cover me,
I'm going in...

Last week,
Ralph Mellor had asked whether currying assumptions could be overridden when the curried function was called and Luke Palmer had said he didn't think so.
This week Damian answered with a rather more authoritative "No,
they can't be overridden,
just make a call to the original function.".
Ralph had also wondered if there would be a way to specify whether currying assumptions were made by binding or by copying a value (currently,
they get bound,
just like they do when you call a function normally (I wonder what happens when the function prototype specifies is copy)).
Damian said that,
if you wanted to make an assumption based on a copy then you needed to explicitly make that copy.

Stéphane Payrard spotted a possible ambiguity in Perl 6's grammar.
He wanted to know if

... but foo('bar')

set the property 'foo' to the value 'bar',
or did it create a property with the name being the value returned by a function call of foo('bar').
He wondered what the syntax would be to get the 'other' meaning.
Luke Palmer thought the first part was that the property 'foo' would get set to 'bar' (so do I,
unless the thing implementing the property has some special semantics).
He suggested that to force the call to the function to get a property name one would do one of:

Mark J.
Reed asked about elegant ways of initializing shared variables.
He wanted something a little neater than the blunderbuss of a BEGIN block.
Larry obliged with one of his 'thinking aloud' posts which,
while not giving us a final answer does give us a few signposts.
It's looking like we'll have traits along the lines of:

state $where is begin($value);
state $where is check($value);
state $where is init($value);
state $where is first($value);

David Storrs was a little worried about the possible clash between the new returns keyword -- introduced in Apocalypse 6 -- and return.
Michael Lazzaro pointed out that the 'possible clash' was almost certainly deliberate,
after all:

sub foo returns Bar {...}

reads rather well.
David had used the example my $spot returns Dog,
which does look rather ugly,
but Michael pointed out,
in the case of a variable declaration,
it made more sense to use my $spot of Dog or even my Dog $spot.
Michael commented that this choice of syntax meant the programmer was able to pick the most readable phrase for a given situation.

David Storrs wondered if the new .wrap method,
which returns a unique id identifying the particular 'wrapper' could have an associated warning if the resulting id wasn't stored somewhere.
Adam D.
Lopresto and Austin Hastings weren't keen...

David Storrs asked for a 'micro-Exegesis' on the difference between - $foo {...}> and sub ($foo) {...} since they both seemed to generate anonymous subroutines.
There were an awful lot of responses to this.
Essentially the difference is that a 'pointy block' (my coinage I think) is just a block that has a signature.
The main difference is what happens to a return.

In a block or a pointy block,
a return returns from the subroutine that lexically contains that block,
not simply from the block itself.
If you want to leave a block prematurely without returning from its enclosing subroutine,
you would use the leave keyword.

This distinction between a Block and a Sub allows for some rather neat (Smalltalkish) idioms

This is a somewhat contrived example,
but I think it's useful as an illustration.
If a Block were exactly the same as a sub,
then the return in find_user would return to the middle of the while loop in iterate_over_file and iterate_over_file would only return after it had gone through every line in the password file,
which would mean that find_user would always return undef.
However,
a return from inside a block returns from the subroutine containing the block so find_user behaves as expected and we get to write powerful control structures without having to resort to macros.
I do wonder if the it would be possible for a function like iterate_over_file to CATCH the block's Return exception though...

The debate over declaring non optional named parameters continued as Damian joining in.
The current consensus appears to be that the various optional/named/slurpy shorthands introduced in Apocalypse 6 should stay pretty much as they are,
but that it should be possible to declare more complex parameter requirements using sensibly named traits.
John Siracusa still wants a more 'powerful' shorthand,
but there doesn't seem to be anyone taking his side on that.

Multimethods still appear to be causing some confusion,
mostly to do with how they are called and dispatched,
and which method parameters participate in the dispatch.
There's a largish contingent (and I probably my count myself a member of that contingent,
spot the bias) who would like to be able to write:

which would first try to dispatch to Point's make_rectangle 'unimethod',
only attempting to dispatch via a multimethod if there is no such method.
Personally,
I think there's room for a spoonful or two of syntactic sugar to allow for the 'method variant' style of declaration as well as the full on generic multimethod style (which would,
of course,
underpin the more restricted method variant style).
However,
if it doesn't exist out of the box I expect someone (me?) will write a set of macros to make things work.

In the message referenced,
Damian explains the current state of the multimethod art...

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.

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:

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!";).

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.

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:

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.

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?

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: