2009-10-29 52 views
83

试图用Clojure以下,期待有类非延迟序列返回:我如何偷懒序列转换为非懒惰Clojure中

(.getClass (doall (take 3 (repeatedly rand)))) 

然而,这仍然返回clojure.lang.LazySeq。我的猜测是doall确实评估整个序列,但返回原始序列,因为它仍然用于记忆。

那么从懒惰创建非惰性序列的惯用方法是什么?

+0

我很惊讶没有人问你为什么要关注'doall'的返回值的实际类型 – tar 2017-11-01 17:14:57

+0

你可以转换成矢量:'(vec(take 3(repeated rand)))' – Kris 2018-01-23 12:33:50

回答

139

doall是你所需要的。仅仅因为seq有类型LazySeq并不意味着它有待评估。懒惰的seqs缓存他们的结果,所以你所需要做的只是一次走懒惰seq(就像doall一样),以强制所有这些,从而使其不会懒惰。 seq确实不是强制对整个集合进行评估。

+2

I'已经将其改为已接受的答案。在相关说明中,通过什么方法可以确定LazySeq是否先前已经过评估? – 2009-10-29 14:16:31

+10

我相信你只是叫'实现?'。 – toofarsideways 2012-02-01 02:40:14

+1

可能应该有一个“实现”操作来匹配'实现?'。 – 2017-02-01 14:07:28

4
(.getClass (into '() (take 3 (repeatedly rand)))) 
+3

这是一个可怕的想法。它反转输入序列。 – amalloy 2011-08-16 17:52:27

+3

当然,在这种情况下,反转输入没有区别,因为它们只是3个随机数.... :-) – mikera 2013-01-03 00:24:37

57

这在某种程度上是一个分类问题。 懒惰序列只是一种类型的序列,因为它是一个列表,向量或映射。因此,答案当然是“这取决于你想要得到什么类型的非懒序列:

  • 的前懒(完全评估)懒惰序列(doall ...)
  • 列表:
    从任你选顺序访问(apply list (my-lazy-seq)) OR (into() ...)
  • 供以后随机访问的载体(vec (my-lazy-seq))
  • 地图或者如果你有一些特殊用途的集合。

您可以拥有最适合您需要的任何类型的序列。

+0

这是最好的答案。 – 2014-07-25 16:20:17

+3

接受的答案在技术上是正确的,但是这个答案对我来说最有用。我试图在vector上映射一个函数,然后将结果吐在一个文件中,甚至在调用doall之后,文件中包含“[email protected]”而不是序列的内容。在返回的值映射上调用vec让我得到了我需要吐出的文件。 – 2015-11-23 23:17:29

+1

@JesseRosalia很高兴知道所有SO中唯一的Rich Hickey响应在技术上是正确的。 ;-) – 2016-03-15 21:02:44

18

这个有钱人似乎知道他的clojure,是绝对正确的。
Buth我觉得这个代码片段,使用你的榜样,可能是一个有益的补充这样一个问题:

=> (realized? (take 3 (repeatedly rand))) 
false 
=> (realized? (doall (take 3 (repeatedly rand)))) 
true 

事实上并没有改变,但实现已经

+2

但是,值得注意的是,你不需要强制'实现'的整个序列返回'true'。例如。 '(让[r(range)r?(real?r)](doall(take 1 r))[r?(real?r)])=> [false true]' – 2014-04-21 17:45:13

+15

这位有钱人:D haha​​ – nimrod 2014-08-26 04:40:28

+7

@ nimrod :)然而,双关语意味着在“h's clojure”。 – Peter 2014-11-04 08:31:17

6

我这个迷迷糊糊这个blog关于doall的帖子不是递归的。为此,我发现在帖子中的第一条评论做了诀窍。沿着线的东西:

(use 'closure.walk) 
(postwalk identity nested-lazy-thing) 

我发现这个有用的单元测试,我想强制的map一些嵌套应用评估,以迫使一个错误条件。