迭代 (/) 多价函数

Iterate (/) a multivalent function

如何迭代多价等级 (>1) 的函数,例如f:{[x;y] ...} 下一个迭代步骤中的函数输入取决于上一个迭代步骤? the reference manual 中的示例仅迭代一元函数。

我能够通过将参数字典(状态)传递给一元函数来间接(并且详细地)实现这一点:

f:{[arg] key[arg]!(min arg;arg[`y]-2)}                                                          
f/[{0<x`x};`x`y!6 3]

注意投影,例如f[x;]/[whilecond;y] 仅适用于下一个迭代步骤中的 x 确实 而不是 取决于结果的情况最后一次迭代(即当 x 与路径无关时)。

与“/”和“\”一起使用的函数只能接受上次迭代的结果作为单个项目,这意味着只有 1 个函数参数保留用于结果。从这个意义上说,它是一元的。

对于多个输入参数依赖于最后一次迭代结果的函数,一种解决方案是将该函数包装在一元函数中,并使用应用运算符在最后一次迭代结果上执行该函数。

例如:

      q) g:{(min x,y;y-2)}  / function with rank 2
      q) f:{x . y}[g;]   / function g wrapped inside unary function to iterate
      q) f/[{0<x 0};6 3]

关于 Rahul 的回答,您可以使用以下方法之一(稍微不那么冗长)来获得相同的结果:

q)g:{(min x,y;y-2)}
q)(g .)/[{0<x 0};6 3]
-1 -3
q).[g]/[{0<x 0};6 3]
-1 -3

或者,您可以使用 .z.s self 函数,它递归调用函数 g 并将最后一次迭代的输出作为其参数。例如,

q)g:{[x;y] x: min x,y; y:y-2; $[x<0; (x;y); .z.s[x;y]]}
q)g[6;3]
-1 -3

随着时间的推移,我偶然发现了不需要圆括号或方括号的更短的方法:

q)g:{(min x,y;y-2)}
q){0<x 0} g//6 3
-1 -3

为什么双 over (//) 有效? / 副词有时可以用来代替 . (apply) 运算符:

q)(*) . 2 3
6
q)(*/) 2 3
6