J语言.我想用函数的形式来表示结果

  • 本文关键字:表示 结果 函数 语言
  • 更新时间 :
  • 英文 :

(+/%#)0:`(>:@$:)@.(3 :'?2')"0 i.10000

工作,我想。答案趋向于1。现在我想用

的形式来表示这个结果
f =: (+/%#)0:`(>:@$:)@.(3 :'?2')"0 i.
f 10000

行不通。

隐式与显式合成

在J中通过并置将几个动词串在一起不会创建一个管道,它创建了一个"动词序列",具有不同的语义。

名词短语:

foo bar bar buz 10000

不同于动词短语:

f =: foo bar baz buz
f 10000

如果你想要一个动词管道,你必须使用某种形式的显式组合(即表示,而不是暗示)。

最常见的是,管道由单复数动词组成(将一个输入转换为一个输出,它成为下一个动词的输入),所以我们使用@:(或@,但使用它需要更注意细节),因此与原始名词短语等价的动词将是:

f =: foo @: bar @: baz @: buz
f 10000

复合和匿名递归

考虑到这一点,在你的情况下,我们可能会天真地写:

(+/%#) @: (0:`(>:@$:)@.(3 :'?2')"0) @: i.

注意将中间的动词(0:`(>:@$:)@.(3 :'?2')"0)包在括号中,因为我们想要应用该动词,并且只应用该动词,在第0级("0),特别是将平均值(+/ % #)应用于整个结果,而不是每个单独的结果。

但是如果我们这样做并运行它,我们很快就会遇到一个问题:无限递归

在原名词短语中,动词0:`(>:@$:)@.(3 :'?2')"0单独存在,因此该动词中的$:(匿名递归)指代0:`(>:@$:)@.(3 :'?2')"0,仅指代0:`(>:@$:)@.(3 :'?2')"0

然而,一旦我们将三个动词的序列重新制定为一个管道(f,上文),那么$:就嵌入到f中,因此指的是f

意思是,在f的这个公式中,当$:递归到一个1上时,首先,i.被应用到这个1上,得到,0,然后?产生一个随机比特,它有50%的概率是1,然后$:递归到这个1上,i.被应用到....

这是一个在j中很常见的陷阱。

隔离$:

你可以把你的代码分成更小的,命名的片段:

f          =:  mean @: converge @: i.
  mean     =:  +/ % #
  converge =:  0:`(>:@$:)@.(3 :'?2')"0

,因为它隔离了$:,所以确保它只引用converge

同样,您可以将$:嵌入到一个匿名显式上下文中,本质上限制了它的权限:

f =:  (+/%#) @: (verb def '0:`(>:@$:)@.(3 :'?2')"0 y') @: i.

这就像给$:戴上眼罩:现在它看不到verb def外面了。一些默认的纯粹主义者可能会对这种方法犹豫不决,但是当使用f.来固定带有嵌入式$:的定义时,J解释器本身曾经使用过这种策略。

解决方案

鉴于您使用3 : '?2',您似乎对匿名显式上下文感到满意。如果是这样的话,那么也许值得全力以赴,将原始的、未经修改的名词短语作为明确的动词使用:

meanConverge =: verb define
   (+/%#) 0:`(>:@$:)@.(3 :'?2')"0 i. y
)

但是,如果你更喜欢一个纯粹的隐性解决方案,并且想要完全在其他方向上,我们甚至可以消除3 : '?2'显式代码:

f          =:  mean @: converge @: i.
  mean     =:  +/ % #
  converge =:  0:`(>:@$:)@.(?@2:)"0

当然,有一些方法可以重写动词来完全避免递归,但这可能违背了练习的目的。

最新更新