那么让我们来看看发生了什么。
首先是序列生成器...,它需要一个起始值列表、一个代码块本身和一个结束点。
它使用起始值来生成列表中的每个下一项,所以让我们从 @pascal[0] 开始,这很简单:[1]
对于@pascal[1],我们使用@pascal[0] 中的值调用代码块,如下所示:
sub ( $array ) {
[0, |$array Z+ |$array, 0]
}
你会注意到我已经把它变成了一个潜艇,这只是为了让我可以更容易地解释事情。在匿名代码块中,$_ 是传入的数据,我称之为$array。那么$array == [1]时我们运行什么代码呢?
[0, |[1] Z+ |[1], 0] => [1,1]
所以这里有一个问题,如果我们不使用 | 会发生什么?
[0, [1] Z+ [1], 0] => [1,1]
都是一样的!那为什么会在那里?那么如果我们设置$array == [3] 会发生什么?
[0, [3] Z+ [3], 0] => [1,1]
奇怪吗?不,因为Z+ 会这样转换:
[0, [3] Z+ [3], 0] => [0 + [3], [3] + 0] => [1,1]
Z 通过使用给定运算符+ 压缩元素来创建一个新列表。 + 正在进行数值计算,数组的数值表示是其中元素的数量,在这种情况下,两次都是 1。
这就是| slip 运算符的用武之地,它将给定的数组滑动到它所在的列表上下文中打开合并。所以让我们回到@pascal[1]
[0, |[1] Z+ |[1], 0] => [0, 1 Z+ 1, 0] => [0 + 1, 1 + 0] => [1,1]
好的.. 所以@pascal[2] 正在调用同一个块,但现在传入[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]
等到无限!
我希望这有助于解释发生了什么?