【问题标题】:How can I generate the Fibonacci sequence using Clojure?如何使用 Clojure 生成斐波那契数列?
【发布时间】:2011-08-07 00:36:40
【问题描述】:
(ns src.helloworld)

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

(fibonacci 0 1)

我是函数式编程的新手,并决定开始学习 Clojure,因为它与 C#非常不同。我想拓宽我的视野。

这是我得到的错误:

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=>

数学问题从来不是我的强项,我也从来没有真正做过像这样操纵数字的东西,所以我希望你能给我任何指导。

请不要给我完整的解决方案。

最好是我想要一些好的提示,也许是它应该是什么样子的骨架。

【问题讨论】:

    标签: clojure fibonacci


    【解决方案1】:
    (fibonacci (+ b 1) a + b)
    

    这里您使用四个参数调用函数fibonacci(+ b 1) 的结果、变量a 的值、函数+ 和变量b 的值。由于 fibonacci 被定义为只接受两个参数,因此您会得到您所做的错误。

    修复此问题后,您将收到堆栈溢出错误,而看不到任何输出。这是因为您将对fibonacci 的递归调用作为println 的参数。所以它会在执行println之前尝试执行递归调用。由于递归是无限的,对println 的调用将永远不会发生。你应该做的是先打印号码,然后递归调用fibonacci

    一旦你这样做了,程序会打印很多数字,但堆栈最终还是会溢出。这是因为 clojure 没有优化掉尾调用,所以即使使用尾递归,无限递归也会导致堆栈溢出。为了防止这种情况发生,请使用recur 形式而不是正常的递归。

    除了这些点之外,当您错误地执行斐波那契数列时,您的程序将打印错误的数字。

    【讨论】:

      【解决方案2】:

      这里提示您为什么遇到错误。您将以下四个参数传递给fibonacci

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

      这仍然不会给你一个工作函数,这里有一个提示:什么会导致代码停止执行并向用户返回一个值?

      【讨论】:

        【解决方案3】:

        其他答案向您解释了函数调用中的错误。修复后,您应该考虑使用循环/递归,这将进行尾调用优化,因此不为每个递归调用使用堆栈。如果不给你整个事情,就很难给出一个例子:-/ 这是另一个线程,他们在 clojure 中使用递归计算阶乘:Factorial

        【讨论】:

        • 将像! 这样的简单递归函数制作成尾递归版本比为fibonacci(有两个自调用)执行此操作要容易得多。你不能再机械地去做了;相反,您必须利用有关斐波那契递归树外观的特定领域知识。在这种情况下是可能的,但并非对每个双递归函数都适用。
        • @amalloy:Sergio 的fibonacci 函数中只有一个递归调用。
        【解决方案4】:

        当我通过一些类似的代码 katas 来学习时,我发现这个网站很有帮助。 Coding Kata。他们将 fib 序列作为黄带 kata。他们还发布了人们以多种语言发布的解决方案(Clojure 就是其中之一)。这样一来,您就可以将自己的答案与其他人进行比较,看看您是否可以找到任何提示或更好的做事方式。

        【讨论】:

          【解决方案5】:

          完成后,您不妨看看 Stu Halloway 在 Programming Clojure 中的 Christophe Grand 的 Fibonacci 解决方案。这是我见过的最优雅的解决方案。它在第 1 版的第 137 页上(因为我听说有第 2 版即将出版)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-12-18
            • 2015-04-25
            • 2017-11-13
            • 1970-01-01
            • 2018-05-11
            • 1970-01-01
            • 2012-04-26
            • 2011-02-20
            相关资源
            最近更新 更多