我是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.'
所以,我要求有人解释我在这里做错了什么。
答案 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-2
和n-1
,然后将这两个fibn
加在一起号。
最后,"0
用于列表处理,M.
用于记忆。从性能角度来看,M.
非常重要,因为规范定义的直接实现会过度地调用fib(2)
。你可以通过内置的memoization副词来获得你的蛋糕(一个简单的定义)并吃掉它(性能良好)。
此特定定义的来源:this page上的f0b
。