在J中创建递归默认函数

see*_*equ 6 recursion j tacit-programming

我是J的新手,我一直在尝试创建一个Fibonacci函数作为练习(总是我学习语言时创建的第二个函数).我无法弄清楚我的做法究竟出了什么问题.我试图将它定义为默认,但如果参数大于1则会挂起.

fib =: [ ` (($: (]-1)) + ($: (]-2))) @. (>&1)
Run Code Online (Sandbox Code Playgroud)

我也试图明确地创建它,并且工作正常.

fib =: 3 : 'if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.'
Run Code Online (Sandbox Code Playgroud)

我试图通过用13代替3来创建一个默认,但它引发了一个错误.

   fib =: 13 : 'if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.'
|spelling error
|   if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.
|   ^
|   fib=:    13 :'if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.'
Run Code Online (Sandbox Code Playgroud)

所以,我要求有人解释我在这里做错了什么.

rat*_*lis 4

我认为这是一个更清晰、更简洁的替代方案:

fibn =: (-&2 +&$: -&1)^:(1&<) M."0
Run Code Online (Sandbox Code Playgroud)

与更规范的(伪代码)定义进行比较:

fib(n) = fib(n-1) + fib(n-2) if n > 2 else n
Run Code Online (Sandbox Code Playgroud)

首先,最好使用,而不是使用使用动名词的[ `with 。对于,使用连词更为惯用;意思是“什么也不做”,意思是“做一次”,所以意图很明确。更适合非平凡的行为。@. (>&1)^:(1&<)f(n) if cond(n) else n^:^:0^:1@.

其次,使用&bond/compose 连接词可以显着简化训练。[:和的重复使用]相当混乱且不透明。使用将&相关操作放在一起进行重构:首先,分成n两个,即n-2和,然后,将这两个数字n-1相加。fibn

最后,"0用于列表处理和M.记忆。M.从性能角度来看相当重要,因为规范定义的直接实现会调用fib(2)过多。通过内置的记忆副词,您可以拥有蛋糕(一个简单的定义)并吃掉它(良好的性能)。

此特定定义的来源:f0b此页面上。