首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >下面的Clojure程序有什么问题?Fibonacci记忆版

下面的Clojure程序有什么问题?Fibonacci记忆版
EN

Stack Overflow用户
提问于 2015-05-27 19:41:48
回答 2查看 102关注 0票数 2
代码语言:javascript
复制
(def fibVal {1 1 2 1})

(defn fibonacci [x]               
  (if (false? (get fibVal x false)) 
    (do
      (println (str "Evaluating " x))
      (def fibVal (assoc fibVal x (+ (fibonacci(- x 1)) (fibonacci(- x 2)))))
      (println (str x " Evaluated to " (fibVal x)))
      (fibVal x)                                
    )
    (get fibVal x)
  )
)

产出(fibonacci 5)

评价5

评价4

评价3

3项评价改为2项

4项评价改为3项

评价3

3项评价改为2项

评价5至5

5

3被评估两次,而在回忆录版本中,应该只评估一次。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-27 20:41:30

您的程序的问题是形式:

代码语言:javascript
复制
(def fibVal (assoc fibVal
                x (+ (fibonacci (- x 1)) 
                     (fibonacci (- x 2)))))

在第一行中使用的fibVal将在递归调用编写新版本之前计算为其当前值。当这个fibVal表达式最后计算时,不管它们对def变量做了什么,都会被遗忘,因为在调用它们之前,它就变成了fibVal,并将它们的返回值与x相关联。

def是用于vor顶级声明的,而不是用于在递归过程中变异全局vars。

而且,您的递归实现不是迭代的,因此它会在足够高的n个地方破坏堆栈。

下面是一个带有回忆录的有状态迭代实现的示例:

代码语言:javascript
复制
(def fib-cache (atom [0 1]))

(defn- calc-nth-fib
  [fibs n]
  (reduce (fn [fibs n]
            (assoc fibs n
                   (apply + (take 2 (rseq fibs)))))
          fibs
          (range (count fibs) (inc n))))

(defn fibonacci [x]
  (or (get @fib-cache x)
      (-> fib-cache
          (swap! calc-nth-fib x)
          (nth x))))

请注意,此示例并不表示在Clojure中查找nth Fibonacci的惯用方法,因为这需要在设计延迟序列的单个线程上生成整个序列,直到n个数列。它们提供隐式缓存,并针对所需的usecase进行优化。

对于一个惯用的Fibonacci实现,请参考许多懒散斐波纳契实现中的一个,如果有必要,请参考学习懒散序列。

票数 2
EN

Stack Overflow用户

发布于 2015-05-27 20:34:11

除了顶级表单之外,在任何情况下使用def都不是线程安全的,也不能保证在您使用它的过程中工作。对于存储这样变化的状态,您很可能希望使用一个可变的状态选项,如原子、参考或代理。

在这种情况下,原子将是一个不错的选择。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30491711

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档