[Perl 6 page]

Parameter Passing Examples

These are examples of passing parameters, with discussions and detailed analyses. This might be useful as a cookbook to find the effect you are wanting, or as a guide to understand the subtleties of the final semantics.

Note that the HTML ids will not change even if the order of the examples change, so you can href them.

See notes at the bottom. Is this even on the right track?

Example 1

sub f1 ($x) { ... }
sub f2 (@y) { ... }

my @A = 1,2,3;

f1(@A);
f2(@A);

In Perl 6, you don’t have to jump through hoops to pass a “whole array”. Both example parameters ($x and @y) are non-slurpy. Even though @y is an array, it still eats one thing from the parameter list passed in.

In fact, both functions are mostly alike in how the parameters end up being used in the body. In the case of f2, @y becomes a read-only alias for @A. You treat it just like any normal array variable, just don’t write to it.

Surprisingly to Perl 5 users, the $x variable works the same way. You can code $x[2], just like @y[2]. You can pass either to another function that wants “an array”. It works differently just beneath the surface, though.

The $x variable is bound to an Item container, and that container contains exactly one item, which is the @A object. So, compared to f2, there is an extra level of indirection. It is like a reference in Perl 5, except it operates invisibly. Almost any time you refer to an Item variable (that is, one declared with the $ sigil), the usage is automatically forwarded to the contained item instead.

So any operation on @y refers to the Array object which is the same object as @A is bound to. (Most) any operation on $x starts off referring to the Item object, but is then forwarded to the thing inside, which is the @A object.

The formal machinery of the passing needs to take the difference into account, too. In both calls, you start out with an argument Capture containing one item, @A. When the sig binding algorithm works on it, in both cases it is considering a non-slurpy parameter.

I’ll call “the sig binding algorithm” siggy for short.

1 In general, to process the next non-slurpy positional parameter, siggy extracts the next item from the argument Capture (essentially a shift), and then somehow sets up the parameter to encompass that argument. I’ll call the “shifted” raw argument α0. So far, this is exactly the object stored in the next positional slot of the Capture, which may be additional nested Captures or some context-sensitive thing.

2 Next, because this is headed for a non-slurpy parameter, it imposes item context onto the raw argument. This will take care of nested Captures and context-sensitive things like Nil, but for the Array object, this operation returns it unchanged. So α, the contextified argument, is still the @A object.

3A In the case of @y, siggy sees that it is a “@” kind of variable, so here’s what he does: Coerce the Positional role out of α, and bind the resulting object to the variable. In more general object-oriented terms, this is known as obtaining a specific interface from the object. Since α is a mild-mannered typical Array object, of course it does the Positional role. So calling the method to obtain the Positional role on α again returns the same thing unchanged. And this is bound to the newly minted local variable @y.

3B In the case of $x, siggy sees that it is a “$” kind of variable, so here’s what he does: First, try to coerce the ItemContainer role out of α. If the argument were something that could be bound directly to $x (i.e. a “tied” scalar), it would do that. But the coersion fails, so siggy does something different. This is in fact the usual case for scalar parameters. Siggy creates a new object of type Scalar (the usual built-in item container) and binds that to $x. Meanwhile, α is stored as the contents of that container.

When the Synopses casually refers to “binding” of a scalar variable, the previous paragraph is the full process involved. The scalar variable can directly bind to things desgined to be replacements for the usual Item container (in Perl 5, the “tie” feature does this). But anything else is stored inside an Item container, giving a level of indirection (like Perl 5 references), but that indirection is mostly invisible so most of the time you ignore the presence of the Item container. After all, all your methods go to the contained object, so that’s the object you are dealing with.

Example 2

sub f1 ($x) { ... }
sub f2 (@y) { ... }

f1(Nil);
f2(Nil);

This is similar to Example 1, but this time step 2 has something to do. When siggy asks α0 for item context, the Nil object implements that method to return undef.

For $x, the object is stored in a fresh Item, as before.

For @y, we have a problem. What we really wanted was an empty list. But Nil's behavior is based on Item vs List context, and we are in Item context.

So... non-slurpy is not the same as item context. The processing of the lists is "one item", but once that item is identified, it is in list context. If that's right, the wording in the synopses needs work, since it gets those concepts terribly mixed up. S06 states that corresponding arguments for Required Parameters and Optional parameters are evaluated in item context; as opposed to the slurpy parameters a.k.a. List Parameters, evaluated in list context.

On the other hand, S06 isn't showing any @ parameters other than named (which take one item per named argument) and slurpy. So maybe I'm missing something, and f2 isn't even allowed any more? I don't see why not. Otherwise, why would we need a special syntax for the slurpy ones?

I think this would work: Step 1, OK. Step 2, context imposed on argument follows parameter's sigil.

Step 3 is still the same, binding the proper role on whatever step 2 returned, and popping something into an Item in 3B.

Footnotes

ItemContainer: The name of this role is not mentioned in the Synopses. In fact, they seem to conflate the roll with the common concrete class.