如何在clojure中为变量重新赋值
我正在为斐波那契级数做这个Clojure程序如何在clojure中为变量重新赋值,clojure,fibonacci,Clojure,Fibonacci,我正在为斐波那契级数做这个Clojure程序 (def fibonacci [] (def a 0) (def b 0) (def c 1) (def n (atom 0)) (while (<= @n 10) (do (def c (+ a b)) (def a b) (def b c) (println '(a b c)) )(swap! n inc))) (fibonacci) 我不知道如何重新
(def fibonacci []
(def a 0)
(def b 0)
(def c 1)
(def n (atom 0))
(while (<= @n 10)
(do
(def c (+ a b))
(def a b)
(def b c)
(println '(a b c))
)(swap! n inc)))
(fibonacci)
我不知道如何重新分配变量
a
、b
和c
。此外,请建议程序中需要的任何更正。如评论中所述,请使用您通常使用的命令式语言
通过改变变量的值来解决这个问题。但从功能上来说
像Clojure这样的语言的重点是不变性、函数调用和
递归。而你可以找到一个解决方案
,
,或诸如此类,这不是风格
您应该在Clojure中编程(至少对于此类问题)
因此,迭代计算斐波那契数的函数可以
像这样(另见
):
fib iter
是一个局部函数,递归调用自身(通过
).但如文所述
:
由于Clojure使用Java调用约定,因此它不能也不会使
同样的尾部调用优化保证。相反,它提供了重现性
特殊运算符,通过重新绑定和
跳转到最近的封闭循环或功能框架
因此,您可以用
得到
迭代过程,或者您可以使用
这稍微简化了代码:
(defn fibonacci
[n]
(loop [a 1
b 0
count n]
(if (= count 0)
b
(recur (+ a b) a (- count 1)))))
首先,让我们让您的代码正常工作。定义函数的第一个
def
,应该是defn
:
(defn fibonacci []
(def a 0)
(def b 0)
(def c 1)
(def n (atom 0))
(while (<= @n 10)
(do
(def c (+ a b))
(def a b)
(def b c)
(println '(a b c))
)(swap! n inc)))
不是你想要的。问题在于(a b c)
前面的引号,它返回列表中未计算的元素。我们必须取消报价,但我们不希望a
被视为操作员。因此,请输入列表
:
(defn fibonacci []
(def a 0)
(def b 0)
(def c 1)
(def n (atom 0))
(while (<= @n 10)
(do
(def c (+ a b))
(def a b)
(def b c)
(println (list a b c))
)(swap! n inc)))
我们有数字,但不是我们想要的。问题在于,第一个(def c(+a b))
清除了唯一的非零值。我们应该从1
的b
开始,暂时使用c
:
(defn fibonacci []
(def a 0)
(def b 1)
(def n (atom 0))
(while (<= @n 10)
(do
(def c (+ a b))
(def a b)
(def b c)
(println (list a b c))
)(swap! n inc)))
万岁
但是我们可以看到b
和c
是相同的,只需预测下一个a
还有一个更大的问题。使用可变变量不是Clojure的方法。函数打印其计算结果也不是惯用做法:更好地将结果发展为一个序列,这样我们就可以随心所欲了
我们可以这样定义整个斐波那契序列:
(defn fibonacci []
(map second
(iterate
(fn [[a b]] [b (+ a b)])
[0 1])))
只要开发出我们想要的:
(take 10 (fibonacci))
=> (1 1 2 3 5 8 13 21 34 55)
几点提示:定义函数应该由defn完成,而不是def。分配局部变量是由let而不是def完成的。只在一个函数中使用的原子通常意味着您的方法是必需的,而不是功能性的。我建议从一些4clojure.com练习开始,这可以建立你的功能性思维。看起来你是带着一种命令式思维进入的。除了@NielsK的建议之外,也许你可以看看《勇敢与真实》免费书中的
Clojure,或者《从头开始》系列中的Clojure。这需要一些时间来适应,如果你没有已经“进入”Clojure的同事或朋友为你指路,那么你最好的选择就是跟随任何一本关于Clojure的书。上面提到的都很好。@santossahoo很好!从你的代码到我的代码有很大的飞跃:你必须学习和,这使我的计算保持与你的相同的形状。顺便说一句,我做了一些小的修正。我注意到了。再次感谢你
> (fibonacci)
(0 0 0)
(0 0 0)
...
(0 0 0)
=> nil
(defn fibonacci []
(def a 0)
(def b 1)
(def n (atom 0))
(while (<= @n 10)
(do
(def c (+ a b))
(def a b)
(def b c)
(println (list a b c))
)(swap! n inc)))
> (fibonacci)
(1 1 1)
(1 2 2)
(2 3 3)
(3 5 5)
(5 8 8)
(8 13 13)
(13 21 21)
(21 34 34)
(34 55 55)
(55 89 89)
(89 144 144)
=> nil
(defn fibonacci []
(map second
(iterate
(fn [[a b]] [b (+ a b)])
[0 1])))
(take 10 (fibonacci))
=> (1 1 2 3 5 8 13 21 34 55)