gpt4 book ai didi

clojure - 通过连接集合创建惰性序列

转载 作者:行者123 更新时间:2023-12-02 13:28:54 24 4
gpt4 key购买 nike

通过连接集合创建惰性序列。

考虑以下函数:

(defn req []
(Thread/sleep 1000)
(repeat 4 (rand-int 10)))

添加 sleep 是因为该函数最终将是一个http请求,因此它应该模拟延迟。

输出示例:

(req)
;; (8 8 8 8)

(req)
;; (4 4 4 4)

我现在正在考虑一个函数,它通过串联后续 req 结果来创建惰性序列构建。

(take 10 (f req))
;; (3 3 3 3 2 2 2 2 9 9)

这是一种实现:

(defn f [g]
(lazy-seq (concat (g) (f g))))

这是要走的路吗?我以某种方式猜测可能已经有一个可用的抽象。我尝试了lazy-cat,但这个宏似乎只适用于固定数量的给定序列。

<小时/>

事实证明,这是一个有效的抽象:

(take 10 (apply concat (repeatedly req)))

但是,看起来惰性序列的分块会导致 req 的调用频率超过此处所需的频率,如果它是 http 请求,则这是 Not Acceptable 。

最佳答案

惰性序列元素的“不需要”实现正在发生,因为 apply needs to know应用传递函数的参数数量。

快速浏览一下 Clojure 核心库,它似乎没有提供连接序列序列的函数,同时以您想要的方式处理惰性(没有多余地实现传递的惰性序列的元素),因此,您需要自己实现它。

以下是可能的解决方案:

(defn apply-concat [xs]
(lazy-seq
(when-let [s (seq xs)]
(concat (first s) (apply-concat (rest s))))))

然后:

user> (defn req []
(println "--> making request")
[1 2 3 4])
#'user/req
user> (dorun (take 4 (apply-concat (repeatedly req))))
--> making request
nil
user> (dorun (take 5 (apply-concat (repeatedly req))))
--> making request
--> making request
nil
user> (dorun (take 8 (apply-concat (repeatedly req))))
--> making request
--> making request
nil
user> (dorun (take 9 (apply-concat (repeatedly req))))
--> making request
--> making request
--> making request
nil

这种方法的唯一问题是堆栈被破坏的危险,因为 apply-concat 可能是无限递归的。

更新:

准确地说,apply实现了传递惰性序列的(传递函数的arity + 1)元素:

user> (dorun (take 1 (apply (fn [& xs] xs) (repeatedly req))))
--> making request
--> making request
nil
user> (dorun (take 1 (apply (fn [x & xs] xs) (repeatedly req))))
--> making request
--> making request
--> making request
nil
user> (dorun (take 1 (apply (fn [x y & xs] xs) (repeatedly req))))
--> making request
--> making request
--> making request
--> making request
nil

关于clojure - 通过连接集合创建惰性序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41616440/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com