在J中创建递归默认函数

时间:2014-06-11 18:41:24

标签: recursion j tacit-programming

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

fib =: [ ` (($: (]-1)) + ($: (]-2))) @. (>&1)

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

fib =: 3 : 'if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.'

我尝试通过将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.'

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

2 个答案:

答案 0 :(得分:4)

好的,我找到了。我只通过默认生成器运行了递归块并得到了这个块。

   13 : '(f y-1) + (f y-2)'
([: f 1 -~ ]) + [: f 2 -~ ]

然后我把它插入到原始作品中,得到了这个。

fib =: [ ` (([: $: 1 -~ ]) + [: $: 2 -~ ]) @. (>&1)

这就像一个魅力。我还在最后插入" 0以使其接受列表。

答案 1 :(得分:4)

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

fibn =: (-&2 +&$: -&1)^:(1&<) M."0

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

fib(n) = fib(n-1) + fib(n-2) if n > 2 else n

首先,不要将[ `与使用动名词的@. (>&1)一起使用,而是使用^:(1&<)更好。对于f(n) if cond(n) else n,使用^:连词更为惯用; ^:0表示&#34;什么都不做&#34;而^:1表示&#34;做一次,&#34;意图很清楚。 @.更适合非平凡的行为。

其次,使用&键/组合连接可以显着简化列车。重复使用[:]相当混乱和不透明。使用&进行重构会将相关操作放在一起:首先,将n拆分为两个,即n-2n-1,然后将这两个fibn加在一起号。

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

此特定定义的来源:this page上的f0b