In Perl 6, I can iterate a literal sequence:
.say for 0 ... 3;
I can bind to a scalar and iterate that:
my $s := 0 ... 3;
.say for $s;
But I can't bind to a scalar, pass it as an argument, and then iterate that:
my $t := 0 ... 3;
show( $t );
sub show ( $seq ) { .say for $seq }
The subroutine gets a single element of type Seq, but it doesn't iterate it.
0
1
2
3
0
1
2
3
(0 1 2 3)
Does something in the process of preparing the parameter iterate through everything already?
While both $s and $seq are scalars (aka "variables"), $s is bound directly to a Seq value whereas your $seq is bound to an intermediary Scalar (note uppercase S) "container" that in turn contains the Seq. A value held in a Scalar container is not automatically iterated when used with features like for.
In more detail:
my $s := 0 ... 3;
.say for $s;
Because the my variable declaration uses the direct binding operator := for initialization, $s is directly bound to the single Seq value 0 ... 3.
This means the for statement sees a single Seq value, determines that it does the Iterable role, and flattens (iterates) it.
Now consider this:
my $s := 0 ... 3;
my $container = $s;
.say for $container;
Because the second my declaration uses the assignment operator = for initialization, the new variable $container is first bound to a new Scalar container which then "contains" whatever gets assigned.
In keeping with the language wide Slurpy Conventions (in particular: "An Iterable inside a Scalar container does not count"), a for statement does not iterate a value held in a Scalar container, so the .say for $container line only does one say.
A similar situation applies for your original show routine because variable parameter declarations are (semantically) containers by default.
One option is to instead add an is raw trait to your $seq parameter:
sub show ( $seq is raw ) { .say for $seq }
This prevents the usual automatic binding of $seq to a Scalar container (that in turn would contain the Seq value) as part of the call to show.
Another option is to let $seq be bound to a Scalar container but explicitly flatten (iterate) the $seq variable in the body of the show routine using a prefix |:
sub show ( $seq ) { .say for |$seq }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With