J语言。我希望以函数

时间:2016-09-14 16:06:50

标签: j

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

正如我想的那样工作。 答案倾向于1。 现在我想以

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

不起作用。

1 个答案:

答案 0 :(得分:5)

隐式与显式合成

通过J中的并置将几个动词串在一起不会创建管道,它会创建一个“verb train”,它具有不同的语义。

名词短语

foo bar bar buz 10000

动词短语

不同
f =: foo bar baz buz
f 10000

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

最常见的是,管道由monadic动词组成(将一个输入转换为一个输出,后者成为下一个动词的输入),因此我们使用@:(或@,但使用该要求稍微注意细节),所以与原始名词短语的口头对应是:

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

组合和匿名递归

鉴于此,在您的情况下,我们可能会天真地写下:

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

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

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

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

然而,一旦我们将三个动词的序列重新组合成一个管道(f,上面),然后$:嵌入f,因此指的是{{1 }} 的。

意思是,在f的这个表述中,当f对1进行递归时,首先,$:会应用于该{1},从而产生i.,然后{{ 1}}生成一个随机位,有50%的可能性为1,然后,0递归,?应用于....

这是J中的一个很好的陷阱。有两种传统的解决方案。

隔离$:

您可以将代码分解为较小的命名部分:

$:

,因为它隔离了i.,确保它仅引用f =: mean @: converge @: i. mean =: +/ % # converge =: 0:`(>:@$:)@.(3 :'?2')"0

同样,您可以将$:嵌入到匿名显式上下文中,主要限制其权限:

converge

这就像在$:上放置眼罩一样:现在它无法在f =: (+/%#) @: (verb def '0:`(>:@$:)@.(3 :'?2')"0 y') @: i. 之外看到。一些默会纯粹主义者可能会对这种方法犹豫不决,但是当使用$:修复了嵌入verb def的定义时,the J interpreter itself employed this tactic就会出现{{3}}。

解决方案

鉴于您使用$:,您似乎对匿名显式上下文感到满意。如果是这样的话,那么也许它值得全力以赴,只是将原始的,未经改动的名词短语捕获为一个明确的动词:

f.

但是,如果您更喜欢纯粹的默认解决方案,并希望在其他方向上全力以赴,我们甚至可以消除3 : '?2'显式代码:

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

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