如何在这里使用复发? [Clojure的]

时间:2017-10-30 13:07:34

标签: clojure

我以为我理解了复发,但以下用法没有意义:

(fn gcd [a b] 
    (if (= b 0) 
        a 
        (recur b (rem a b))))  

该函数检索两个数字的最大公约数。对于4和2,函数将给出2.

我知道recur可以绑定到函数,但我认为'b'只是在没有任何变化的情况下循环重复。您通常需要输入类似(inc b)的内容以允许循环中的值更改。

我错过了什么?

3 个答案:

答案 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)之类的内容,并在查找答案时看到循环显示的值。