I've come across this code at rosettacode
my @pascal = [1], { [0, |$_ Z+ |$_, 0] } ... Inf;
.say for @pascal[^4];
# ==>
# [1]
# [1 1]
# [1 2 1]
# [1 3 3 1]
Inside the explicit generator block, I know how the individual operators like the list flattening |
and the zip operator Z+
work but I have difficulty comprehending how they cooperate to generate the next array. Can somebody explain in detail how it works? Thank you.
Note: The code is slightly rearranged for brevity, i.e. it's superficially different than the one in Rosetta.
So let's take a look at what's going on.
First up the Sequence generator ...
this takes a list of starting values, a code block itself and and end point.
It uses the starting values to generate each next item in the list so lets start with @pascal[0]
that's simple enough : [1]
For @pascal[1]
we call the code block with our value in @pascal[0]
like so :
sub ( $array ) {
[0, |$array Z+ |$array, 0]
}
You'll note I've made it into a sub, this is just so I can explain things easier. In the anonymous code block $_ is the incoming data and I've called it $array
. So what code to we run when $array == [1]
?
[0, |[1] Z+ |[1], 0] => [1,1]
So here's a question what happens if we don't use the |
?
[0, [1] Z+ [1], 0] => [1,1]
It's the same! So whys it there? Well what happens if we set $array == [3]
?
[0, [3] Z+ [3], 0] => [1,1]
Weird? No, because the Z+
transforms like this :
[0, [3] Z+ [3], 0] => [0 + [3], [3] + 0] => [1,1]
Z
makes a new list by zipping the elements with the given operator +
between them. +
is doing a numerical computation and the Numerical representation of an Array is the number of elements in it, in this case 1 both times.
And this is where the |
slip operator comes in, it slips the array it's given open merging into the list context it's in. So lets go back to @pascal[1]
[0, |[1] Z+ |[1], 0] => [0, 1 Z+ 1, 0] => [0 + 1, 1 + 0] => [1,1]
Ok.. So @pascal[2]
is calling the same block but now passing in [1,1]
[0, |[1, 1] Z+ |[1, 1], 0] => [0, 1, 1 Z+ 1, 1, 0] => [0 + 1, 1 + 1, 1 + 0] => [1,2,1]
And so on into Infinity!
I hope that's helped to explain what's going on?