English 中文(简体)
Clojure惰性序列用法
原标题:Clojure lazy sequence usage

我很难理解如何在Clojure中创建懒惰序列。

宏的文档对我来说一点也不清楚:

Usage: (lazy-seq & body) Takes a body of expressions that returns an ISeq or nil, and yields a Seqable object that will invoke the body only the first time seq is called, and will cache the result and return it on all subsequent seq calls.

我看到的所有例子似乎都有以下作用:

; return everything in the sequence starting at idx n
(defn myseq-after-n [n]
  (...)
)

(def my-lazy-seq
  (lazy-seq (conj [init-value] (myseq-after-n 2)))
)

所以,我不知道的第一件事是,既然lazy-seq在对conj的调用之外,它如何防止conj在求值时生成无限序列?

我的第二个问题是,惰性序列定义总是采用这种通用形式吗?

最佳回答

懒惰的seq调用只在第一次访问时执行主体一次,然后缓存并在将来再次调用时返回相同的结果。

如果您想使用它来构建长(甚至无限)序列,那么您需要在返回的序列中递归嵌套其他懒惰的seq调用。以下是我能想到的最简单的情况:

(defn ints-from [n]
  (cons n (lazy-seq (ints-from (inc n)))))

(take 10 (ints-from 7))
=> (7 8 9 10 11 12 13 14 15 16)

任何(ints-from n)调用都会生成一个以n开头的序列,后跟一个惰性序列(ints-from(inc n))。它是一个无限列表,但这不是问题,因为lazy-seq确保(int-from(incn))只在需要时被调用。你可以尝试完全相同的代码,而不需要懒惰的seq,你会很快得到StackOverflowError。

懒惰序列只是创建懒惰序列的多种可能方法之一,而且它通常不是最方便的。以下是创建惰性序列的其他一些有趣/有用的方法:

; range is an easy way to get an infinite lazy sequence of integers, starting with zero     
(take 10 (range))
=> (0 1 2 3 4 5 6 7 8 9)

; map produces lazy sequences, so the following is lazy 
(take 10 (map #(* % %) (range)))
=> (0 1 4 9 16 25 36 49 64 81)

; iterate is a good way of making infinite sequenes of the form x, f(x), f(f(x))..... 
(take 10 (iterate (partial * 2) 1))
=> (1 2 4 8 16 32 64 128 256 512)
问题回答

暂无回答




相关问题
How to improve Clojures error messages

I ve been playing a bit with Clojure and so far is fairly impressed, but one thing that I keep running into is wierd error messages from Clojure. This comes in two forms: Java errors, like null ...

clojure rmi classpath problem

I am trying to use clojure to implement a "plugin" for some vendor supplied software. Here is a little background on the vendor supplied software. It expects me to implement a particular interface ...

Help translating this Java codeblock to Clojure?

I m getting my feet wet with Clojure, and trying to get used to functional programming. I ve been translating various imperative functions from other languages into their Clojure equivalents -- and ...

Is functional Clojure or imperative Groovy more readable?

OK, no cheating now. No, really, take a minute or two and try this out. What does "positions" do? Edit: simplified according to cgrand s suggestion. (defn redux [[current next] flag] [(if flag ...

taking java method names as function arg in clojure

All, I want to create a function that takes a symbol representing a java method and applies it to some object: (user=> (defn f [m] (. "foo" (m))) When I execute this, I get a result much ...

how to efficiently apply a medium-weight function in parallel

I m looking to map a modestly-expensive function onto a large lazy seq in parallel. pmap is great but i m loosing to much to context switching. I think I need to increase the size of the chunk of work ...

热门标签