我还没有完整的答案,但是 Roger Hui 的 this essay 有一个默认构造,您可以使用它来替换显式的 while 循环。另一种(相关的)途径是将块的内部逻辑变成这样的默认表达:
FUNWITHTACIT =: ] , {: + {: +. 1 + #
rowland =: monad define
result =. >a:
t =. 7x
while. (# result) < y do.
t =. FUNWITHTACIT t
d =. | -/ _2 {. t
result =. ~.result,((d>1)#d)
end.
result
)
(不过,为了提高效率,您可能希望保留 if 块,因为我编写代码的方式是修改 result,而不管条件是否满足——如果不满足,则修改无效。if 逻辑甚至可以通过使用 Agenda 运算符写回默认表达式。)
一个完整的解决方案包括找出如何将 while 循环中的所有逻辑表示为单个函数,然后使用 Roger 的技巧将 while 逻辑实现为默认表达式。我会看看我能找到什么。
顺便说一句,我让 J 为我构建 FUNWITHTACIT,方法是获取代码的前几行,手动替换为变量值声明的函数(我可以这样做,因为它们都在单个参数以不同的方式),用y替换t的每个实例,并告诉J构建结果表达式的默认等价物:
]FUNWITHTACIT =: 13 : 'y,({:y)+(1+#y)+.({:y)'
] , {: + {: +. 1 + #
使用 13 声明 monad 是 J 知道获取 monad 的方式(否则使用 3 : 0 或 monad define 显式声明,如您在程序中编写的那样)并将显式表达式转换为默认表达式。
编辑:
以下是我在评论中提到的为大道 (2) 编写的函数:
candfun =: 3 : '(] , {: + {: +. 1 + #)^:(y) 7'
firstdiff =: [: | 2 -/\ ]
triage =: [: /:~ [: ~. 1&~: # ]
rowland2 =: triage @firstdiff @candfun
此函数使用 Rowland 递归关系生成前 n 个候选数,评估它们的一阶差分,丢弃所有等于 1 的一阶差分,丢弃所有重复项,并按升序对它们进行排序。我认为这还不完全令人满意,因为参数设置了要尝试的候选人数量而不是结果数量。但是,它仍然在进步。
例子:
rowland2 1000
3 5 7 11 13 23 47 101 233 467 941
这是我发布的第一个函数的一个版本,将每个参数的大小保持在最小:
NB. rowrec takes y=(n,an) where n is the index and a(n) is the
NB. nth member of the rowland candidate sequence. The base case
NB. is rowrec 1 7. The output is (n+1,a(n+1)).
rowrec =: (1 + {.) , }. + [: +./ 1 0 + ]
rowland3 =: 3 : 0
result =. >a:
t =. 1 7
while. y > #result do.
ts =. (<"1)2 2 $ t,rowrec t
fdiff =. |2-/\,>(}.&.>) ts
if. 1~:fdiff do.
result =. ~. result,fdiff
end.
t =. ,>}.ts
end.
/:~ result
)
找到前 y 个不同的 Rowland 素数并按升序显示它们:
rowland3 20
3 5 7 11 13 23 47 53 101 233 467 941 1889 3779 7559 15131 30323 60647 121403 242807
这个函数的大部分复杂性来自我对盒装数组的处理。这不是漂亮的代码,但它只在计算过程中将4+#result 的许多数据元素(以对数规模增长)保留在内存中。原始函数rowland 将(#t)+(#result) 元素保留在内存中(以线性比例增长)。 rowland2 y 构建了一个由y-many 元素组成的数组,这使得它的内存配置文件几乎与rowland 相同,即使它永远不会超过指定的范围。我喜欢 rowland2 的紧凑性,但没有公式来预测生成 n 多个不同素数所需的 y 的确切大小,该任务需要在反复试验的基础上完成,因此可能使用在冗余计算上比rowland 或rowland3 更多的周期。 rowland3 可能比我的rowland 版本更有效,因为FUNWITHTACIT 在每次循环迭代时都会重新计算#t -- rowland3 只是增加一个计数器,计算量较小。
不过,我对rowland3 的显式控制结构并不满意。似乎应该有一种方法可以使用递归或其他方式来完成此行为。