J:为什么`f ^:proposition ^:_ y`代表一个while循环?

时间:2013-09-08 09:52:18

标签: while-loop j

正如标题所说,我不明白为什么f^:proposition^:_ y是一个while循环。我实际上已经使用了几次,但我不明白它是如何工作的。我得到^:重复函数,但我对它在该语句中的双重使用感到困惑。

我也无法理解为什么f^:proposition^:a: y有效。这与前一个迭代相同,但返回所有迭代的值,而不是上一个迭代的值。

a:是一个空框,我得到的是与^:一起使用的特殊含义,但即使在查看字典后我也无法理解它。

感谢。

2 个答案:

答案 0 :(得分:6)

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}}取决于输入(中断条件是布尔值)。

因此,如果输入是“正确的”(即处理已完成),则1将为break_condition,从而0将成为loop_body^:break_condition^:_。显然,loop_body^:0^:_应用loop_body^:0零次,这没有效果。

“没有效果”是保持输入不变;换句话说,它将输入复制到输出......但如果输入与输出匹配,则该功能已达到其极限!显然loop_body检测到这个事实并终止。瞧,一阵!!


¹是的,包括零和负整数,“整数”应该更恰当地读作“任意整数数组”(因此该函数可以同时应用于多个幂)。

答案 1 :(得分:3)

f^:proposition^:_ 是一个while循环。当proposition返回10时,它是(几乎)一个while循环。当proposition返回其他结果时,这是一种奇怪的while循环。

让我们来看一个简单的monadic案例。

f =: +:        NB. Double
v =: 20 > ]    NB. y less than 20

(f^:v^:_) 0     NB. steady case
0
(f^:v^:_) 1     NB. (f^:1) y, until (v y) = 0
32
(f^:v^:_) 2
32
(f^:v^:_) 5
20
(f^:v^:_) 21   NB. (f^:0) y
21

这就是发生的事情:每次v y1时,(f^:1) y都会被执行。 (f^:1) y的结果是新的y,依此类推。

  • 如果y连续两次保持相同→输出y并停止。
  • 如果v y0→输出y并停止。

所以f^:v^:_在这里,就像double while less than 20 (or until the result doesn't change)

一样

让我们看看当v返回2 / 0而不是1 / 0时会发生什么。

 v =: 2 * 20 > ]

(f^:v^:_) 0      NB. steady state
0
(f^:v^:_) 1      NB. (f^:2) 1 = 4 -> (f^:2) 4 = 16 -> (f^:2) 16 = 64 [ -> (f^:0) 64 ]
64
(f^:v^:_) 2      NB. (f^:2) 2 = 8 -> (f^:2) 8 = 32 [ -> (f^:0) 32 ]
32
(f^:v^:_) 5      NB. (f^:2) 5 = 20 [ -> (f^:0) 20 ]
20
(f^:v^:_) 21     NB. [ (f^:0) 21 ]
21

通过玩v,您可以拥有多种“奇怪”循环。 (它甚至可以返回负整数,使用f的倒数)。