2011-04-16 25 views
4
(ns src.helloworld) 

(defn fibonacci[a b] (println a b (fibonacci (+ b 1) a + b))) 

(fibonacci 0 1) 

我是新來功能編程,並決定開始學習Clojure,因爲它的不同於C#。我想擴大我的視野。如何使用Clojure生成斐波那契數列?

這是我得到的錯誤:

Clojure 1.2.0 
java.lang.IllegalArgumentException: 
Wrong number of args (4) passed to: 
helloworld$fibonacci 
(helloworld.clj:0) 1:1 user=> 
#<Namespace src.helloworld> 1:2 src.helloworld=> 

數學問題從來不是我的強項,我從來沒有真正做任何操作這樣的數字,所以我想你可以給任何指導。

請不要給我整個解決方案。

最好我想一些好的提示,也許它應該看起來像一個骨架。

回答

1

其他答案向您解釋函數調用中的錯誤。修復之後,您應該查看使用循環/循環,它將執行尾部調用優化,因此不會爲每次遞歸調用使用堆棧。儘管如此,給出一個例子並不給你所有的東西是非常困難的: - /這裏是另一個線程,他們用clojure中的遞歸計算因子:Factorial

+0

將一個簡單遞歸函數(如'!')轉換爲尾遞歸版本比對'fibonacci'做這個操作要容易得多,該函數有兩個自調用。你不能再機械地去做;相反,您必須利用關於斐波那契遞歸樹外觀的領域特定知識。在這種情況下可能會發生,但不適用於每個雙遞歸函數。 – amalloy 2011-04-16 19:22:55

+1

@amalloy:在Sergio的'fibonacci'函數中只有一個遞歸調用。 – sepp2k 2011-04-16 19:31:06

4
(fibonacci (+ b 1) a + b) 

在這裏,我們調用該函數fibonacci有四個參數:中(+ b 1)結果,變量a的價值,功能+和變量b的價值。由於fibonacci被定義爲只有兩個參數,所以你會得到錯誤。

一旦你解決這個問題,你會得到一個堆棧溢出錯誤,而不會看到任何輸出。這是因爲您將遞歸調用fibonacci作爲參數println。所以它會在執行println之前嘗試執行遞歸調用。由於遞歸是無限的,所以對println的調用永遠不會發生。你應該做的是首先打印數字,然後遞歸地呼叫fibonacci

一旦你這樣做,程序將打印很多數字,但堆棧最終仍會溢出。這是因爲clojure沒有優化尾部調用,所以即使在使用尾部遞歸時,無限遞歸也會導致堆棧溢出。爲了防止這種情況使用recur表單而不是正常的遞歸。

除了這些要點之外,當您錯誤地執行斐波那契序列時,程序將打印錯誤的數字。

3

這裏有一個暗示,你爲什麼得到你所犯的錯誤。你通過了以下四個參數fibonacci

  • (+ b 1)
  • a
  • +
  • b

這仍然不會給你一個工作的功能,這裏是一個暗示有關:什麼都不會導致代碼停止執行,並返回一個值給用戶?

1

當我正在瀏覽一些類似的代碼katas來學習時,我發現這個網站非常有幫助。 Coding Kata。他們將fib序列作爲黃色帶kata。他們也有從多種語言的人發佈的解決方案(Clojure就是其中之一)。這樣,您可以將您的答案與其他人進行比較,看看您是否可以拿起任何提示或更好的做法。

0

當你完成了,你可能希望看看Christophe Grand的Fibonacci解決方案,由Stu Halloway在編程Clojure。這是我見過的最優雅的解決方案。這是在第1版第137頁(因爲我聽說有第二版即將到來)。