Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 函数局部、自参考、惰性斐波那契序列_Clojure_Fibonacci_Local Variables - Fatal编程技术网

Clojure 函数局部、自参考、惰性斐波那契序列

Clojure 函数局部、自参考、惰性斐波那契序列,clojure,fibonacci,local-variables,Clojure,Fibonacci,Local Variables,我想创建一个函数,返回一个延迟扩展的Fibonacci数的无限序列 现在,我可以在顶级名称空间中使用我的序列,如下所示: (def fibonacci-numbers (lazy-cat [0 1] (map + fibonacci-numbers (rest fibonacci-numbers)))) 然而,这意味着,如果我开始大量使用它们,我将失去对垃圾收集的控制 我希望做一些类似的事情: (defn fibonacci-numbers-fn [] (lazy-cat [0 1]

我想创建一个函数,返回一个延迟扩展的Fibonacci数的无限序列

现在,我可以在顶级名称空间中使用我的序列,如下所示:

(def fibonacci-numbers
  (lazy-cat [0 1] (map + fibonacci-numbers (rest fibonacci-numbers))))
然而,这意味着,如果我开始大量使用它们,我将失去对垃圾收集的控制

我希望做一些类似的事情:

(defn fibonacci-numbers-fn []
  (lazy-cat [0 1] (map + (fibonacci-numbers-fn) (rest (fibonacci-numbers-fn)))))
这显然行不通,因为我最终将创建O(2^n)序列。我想我是在问如何在函数本地名称空间中创建一个自引用惰性序列。我该怎么办

编辑:虽然我喜欢amalloy发布的流行解决方案,并且在互联网上到处都可以找到
defn fibs[](映射优先(迭代(fn[[ab]]][b(+ab)])[01]))
,但我对类似于规范的Haskell方式的版本感兴趣:

fibonaccis = 0 : 1 : zipWith (+) fibonaccis (tail fibonaccis)

这就是我试图用我的原始函数来完成的。对我来说,map iterate解决方案的内容类似于“添加前两个元素以创建一个新元素”,而lazy cat解决方案的内容类似于“加入一个具有第一个延迟的流”。我如何才能在顶级名称空间中没有序列的情况下“加入具有第一个延迟的流”?

也许
letfn
就是您要寻找的

(def fibo-nums
  (letfn [(fibo-num-fn []
            (lazy-cat [0 1]
              (map + (fibo-num-fn) (rest (fibo-num-fn)))))]
    fibo-num-fn))
或者,如果您打算手工使用lazy seq:

(letfn [(fibs
          ([]
             (fibs 0 1))
          ([a b]
             (lazy-seq
               (cons a (fibs b (+ a b))))))]
  (take 10 (fibs)))

;; (0 1 1 2 3 5 8 13 21 34)

如果将可选名称放在[]之前,则由
fn
表单定义的函数可以是递归函数。(在本例中,使用的名称为
this


产生序列的实际函数是匿名函数,每次调用它时只产生下一个元素。没有堆栈或堆溢出的可能性(除非您将封闭函数的返回值保存在某个var中)

您可以使用
承诺来解决问题,手动执行haskell自动执行的操作:

(defn fibs []
  (let [fibs (promise)]
    @(doto fibs
       (deliver (list* 0 1 (lazy-seq (map +' @fibs (rest @fibs))))))))

我遇到了一个非常类似的问题,最终选择了以下宏(这基本上比amalloy关于承诺的回答更重要):

这样,您就可以编写:

(defn  fibonacci-numbers-fn []
   (rec-seq fibs (lazy-cat [0 1] (map +' fibs (rest fibs)))))
这几乎就是你想写的


注:rec-seq是递归seq的缩写。

您的
defn
需要
[]
,但我不想进行两个字符的编辑<代码>(╯°□°)╯︵ ┻━┻如果你走这条路,我想你最终会遇到我上面提到的同样的问题;您不断调用该函数并创建新序列。有人能证实吗?我认为您也缺少了一个
[]
,需要在最后调用fibo num fn,而不是返回函数本身:)。嗯,我想我不完全理解您的问题。这是一个很好的解决最初提出的问题的方法。你能想出一种方法让代码按照我的编辑方式阅读吗?
(defn fibs []
  (let [fibs (promise)]
    @(doto fibs
       (deliver (list* 0 1 (lazy-seq (map +' @fibs (rest @fibs))))))))
(defmacro rec-seq [name expr]
   `(let [p# (promise)
           s# (lazy-seq (let [~name @p#] ~expr))]
       (deliver p# s#)
        s#))
(defn  fibonacci-numbers-fn []
   (rec-seq fibs (lazy-cat [0 1] (map +' fibs (rest fibs)))))