Excerpted and adapted from a longer writeup I posted to the J forums in 2009:
while =: ^:break_clause^:_
这是一个可以应用于任何代码的副词(相当于
循环体)来创建一个while循环。如果您以前没有见过,^: 是电源连接。更具体地说,短语f^:n y 将函数f 应用于参数y 恰好n 次。计数n 可能是一个整数或应用于y 的函数会产生一个整数¹。
在上面的副词中,我们看到了两次幂连词,一次在^:break_clause,另一次在^:_ 。我们先讨论后者。 _ 是 J 的无穷大符号。所以,从字面上看,^:_ 是“无限次地应用函数”或“永远重新应用”。这与 while 循环的功能有关,但如果按字面应用,它并不是很有用。
因此,相反,^:_ 及其近亲被定义为“将函数应用到其极限”,即“继续应用该函数直到其输出与输入匹配”。在这种情况下,再次应用该函数将无效,因为下一次迭代将具有与前一次相同的输入(请记住,J 是一种函数式语言)。所以有
再次应用该功能毫无意义:它已达到其极限。
例如:
cos=: 2&o. NB. Cosine function
pi =: 1p1 NB. J's notation for 1*pi^1 analogous to scientific notation 1e1
cos pi
_1
cos cos cos pi
0.857553
cos^:3 pi
0.857553
cos^:10 pi
0.731404
cos^:_ pi NB. Fixed point of cosine
0.739085
在这里,我们一直应用余弦,直到答案停止变化:余弦已达到其固定点,更多的应用是多余的。我们可以通过显示
中间步骤:
cos^:a: pi
3.1415926535897 _1 0.54030230586813 ...73 more... 0.73908513321512 0.73908513321
所以^:_ 将函数应用到其极限。好的,^:break_condition 呢?同样,这是相同的概念:将左侧函数应用到右侧函数指定的次数。在_ (或其等效函数_: )的情况下,输出为“无穷大”,在break_condition 的情况下,输出将为0 或1,具体取决于输入(中断条件是布尔值)。
因此,如果输入是“正确的”(即处理完成),那么 break_condition 将是 0,因此 loop_body^:break_condition^:_ 将变为 loop_body^:0^:_ 。显然,loop_body^:0 应用了 loop_body 零次,没有任何效果。
“没有效果”是保持输入不变;换句话说,它将输入复制到输出......但是如果输入与输出匹配,则函数已达到其极限!显然^:_: 检测到这一事实并终止。瞧,一个while循环!
¹ 是的,包括零整数和负整数,并且“整数”应该更恰当地理解为“任意整数数组”(因此该函数可以同时应用于多个幂)。