(+/%#)0:`(>:@$:)@.(3 :'?2')"0 i.10000
正如我想的那样工作。 答案倾向于1。 现在我想以
的形式表达这个结果f =: (+/%#)0:`(>:@$:)@.(3 :'?2')"0 i.
f 10000
不起作用。
答案 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
)
当然,有一些方法可以重写动词以完全避免递归,但这可能会破坏练习的目的。