我如何避免Clojure的分块行为为惰性seqs我想短路? [英] How do I avoid Clojure's chunking behavior for lazy seqs that I want to short circuit?

查看:179
本文介绍了我如何避免Clojure的分块行为为惰性seqs我想短路?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个长,懒惰的序列,我想减少和测试懒惰。一旦两个顺序元素不是 = (或一些其他谓词)彼此,我想停止消费列表,这是昂贵的生产。是的,这听起来像 take-while ,但进一步阅读。



我想写一些简单而优雅的(假装每个工作原理如 reduce ):

 (每个?=(范围100000000))

但是这不工作,懒惰,所以它挂在无限seqs。我发现这个工作几乎是我想要的:

 (apply =(range 100000000))
  ;;在我的系统上显示四个组块行为,并打印1 2 3 4 
(apply =(map#(do(println%)%)(iterate inc 1)))

; ;这打印0到31
(apply =(map#(do(println%)%)(range)))

我发现一个解决方法使用 take-while count 来检查元素的数量



我应该礼貌地建议Rich Hickey他做一些 reduce 的组合,和每个?短路,或者我缺少已经存在的一些明显的方式?



两个人发布了解决方案,以避免在延迟序列上的分块,但是如何避免分块,当做 apply ,这似乎在分块组四个?



编辑#2:正如Stuart Sierra所说,我独立发现,这不是真正的分块。它只是应用正常作用,所以我把这封闭,给他答案。

解决方案

CORRECTED TWICE :取消延迟延迟序列的更简单方法:

 (defn unchunk [ s] 
(when(seq s)
(lazy-seq
(cons(first s)
(unchunk(next s)))))

省略第一个版本(当...



第二个版本使用第一个而不是 seq RE:您的其他问题,我如何避免分组?

当执行apply时,这似乎是在分组的四个组中消耗



这是由于定义 = ,当给定一系列参数时,强制前4:

 (defn = 
;; ... other arities ...
([xy&更多]
(if(= xy)
(if(next more)
(recur y(first more)(next more))

false)))


I have a long, lazy sequence that I want to reduce and test lazily. As soon as two sequential elements are not = (or some other predicate) to each other, I want to stop consuming the list, which is expensive to produce. Yes, this sounds like take-while, but read further.

I wanted to write something simple and elegant like this (pretending for a minute that every? works like reduce):

(every? = (range 100000000))

But that does not work lazily and so it hangs on infinite seqs. I discovered that this works almost as I wanted:

(apply = (range 100000000))

However, I noticed that sequence chunking was resulting in extra, unnecessary elements being created and tested. At least, this is what I think this is what happening in the following bit of code:

;; Displays chunking behavior in groups of four on my system and prints 1 2 3 4
(apply = (map #(do (println %) %) (iterate inc 1)))

;; This prints 0 to 31
(apply = (map #(do (println %) %) (range)))

I found a workaround using take-while, and count to check the number of elements taken, but that is rather cumbersome.

Should I politely suggest to Rich Hickey that he make some combination of reduce and every? short circuit properly, or am I missing some obvious way that already exists?

EDIT: Two kind people posted solutions for avoiding chunking on the lazy sequences, but how do I avoid chunking when doing the apply, which seems to be consuming in chunked groups of four?

EDIT #2: As Stuart Sierra notes and I discovered independently, this isn't actually chunking. It's just apply acting normally, so I'll call this closed and give him the answer. I included a small function in a separate answer to do the reduce'ing part of the problem, for those who are interested.

解决方案

CORRECTED TWICE: A simpler way to un-chunk a lazy sequence:

(defn unchunk [s]
  (when (seq s)
    (lazy-seq
      (cons (first s)
            (unchunk (next s))))))

First version omitted (when ... so it returned an infinite seq of nil's after the input sequence ended.

Second version used first instead of seq so it stopped on nil.

RE: your other question, "how do I avoid chunking when doing the apply, which seems to be consuming in chunked groups of four":

This is due to the definition of =, which, when given a sequence of arguments, forces the first 4:

(defn =
  ;; ... other arities ...
  ([x y & more]
   (if (= x y)
     (if (next more)
       (recur y (first more) (next more))
       (= y (first more)))
     false)))

这篇关于我如何避免Clojure的分块行为为惰性seqs我想短路?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆