我以为我理解了复发,但以下用法没有意义:
(fn gcd [a b]
(if (= b 0)
a
(recur b (rem a b))))
该函数检索两个数字的最大公约数。对于4和2,函数将给出2.
我知道recur可以绑定到函数,但我认为'b'只是在没有任何变化的情况下循环重复。您通常需要输入类似(inc b)的内容以允许循环中的值更改。
我错过了什么?
答案 0 :(得分:3)
这里的gcd函数使用Euclidean algorithm来找到两个数字的最大公约数。
该函数有效并且终止,因为参数列表包含[a b]
但是b, (rem a b)
调用了recur。请注意,此处b
的位置已更改(从seond位置到第一位)。
a
的值已更改,因为b
的值已分配给它。此外,b
的值已更改,因为(rem a b)
已分配给它(因此减少)。因此,当重复调用时,两个值都会减少,并且最终其中一个值达到0(停止递归)。
答案 1 :(得分:2)
(fn gcd [a b]
(if (= b 0) a
(recur b (rem a b))))
例如,我用参数a = 24,b = 16调用此函数。 只要b不为零,就会递归调用此函数。
(gcd 24 16)
=> (gcd 16 8)) #_"because b=24 doesn't equal to zero and 8 is the reminder of 24/16"
=> (gcd 8 0) #_"0 is the reminder of 16/8"
=> 8
此计算停止,因为b达到零。
答案 2 :(得分:2)
是的,您希望更改递归调用中的值,以便最终您的测试成功,并且您将突破递归。该算法通过使用旧的第二参数的值发送新的第一参数,并且基于旧的第一和第二参数重新计算新的第二参数来完成该算法。
尝试在函数中的if语句之前添加(println "a:" a "b:" b)
之类的内容,并在查找答案时看到循环显示的值。