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 具有core.async的节流功能_Clojure_Clojurescript_Core.async - Fatal编程技术网

Clojure 具有core.async的节流功能

Clojure 具有core.async的节流功能,clojure,clojurescript,core.async,Clojure,Clojurescript,Core.async,应限制函数可能执行的次数。因此,在调用函数后,任何重复调用都应该在一段时间内被忽略。如果同时存在where调用,则应在时间段之后执行最后一个调用 下面是我使用core.async的方法。这里的问题是,额外的调用在通道c中汇总。我需要一个通道,里面只有一个位置,它将被put覆盖!每次都是 (defn throttle [f time] (let [c (chan 1)] (go-loop [] (apply f (<! c)) (<! (timeou

应限制函数可能执行的次数。因此,在调用函数后,任何重复调用都应该在一段时间内被忽略。如果同时存在where调用,则应在时间段之后执行最后一个调用

下面是我使用core.async的方法。这里的问题是,额外的调用在通道c中汇总。我需要一个通道,里面只有一个位置,它将被put覆盖!每次都是

(defn throttle [f time]
  (let [c (chan 1)]
    (go-loop []
      (apply f (<! c))
      (<! (timeout time))
      (recur))
    (fn [& args]
      (put! c (if args args [])))))
有人知道如何解决这个问题吗

解决方案
(除油门[f时间]
(让[c(chan(滑动缓冲器1))]
(转到循环[]
(应用f(您可以使用函数

我会把它复制到这里:

(defn debounce [in ms]
  (let [out (chan)]
    (go-loop [last-val nil]
      (let [val (if (nil? last-val) (<! in) last-val)
            timer (timeout ms)
            [new-val ch] (alts! [in timer])]
        (condp = ch
          timer (do (>! out val) (recur nil))
          in (recur new-val))))
    out))
这是
debounce
的版本,将根据问题的要求输出,即立即为0,然后等待4秒钟,然后是9:

(defn debounce [in ms]
  (let [out (chan)]
    (go-loop [last-val nil
              first-time true]
             (let [val (if (nil? last-val) (<! in) last-val)
                   timer (timeout (if first-time 0 ms))
                   [new-val ch] (alts! [in timer])]
               (condp = ch
                 timer (do (>! out val) (recur nil false))
                 in (recur new-val false))))
    out)) 
(反弹力[以毫秒为单位]
(放[出(陈)]
(go loop[最后一个值为零
第一次正确]
(让[val(如果(无?最后一个val)(!out val)(重复无错误))
在(重复新val false)中)
出局

我使用的是
log
,而不是像你那样使用
print
。你不能依赖
println/print
函数的
core.async
。请参阅以获取解释。

要解决频道问题,你可以使用带有滑动缓冲区的chan:

user> (require '[clojure.core.async :as async])
nil
user> (def c (async/chan (async/sliding-buffer 1)))
#'user/c
user> (async/>!! c 1)
true
user> (async/>!! c 2)
true
user> (async/>!! c 3)
true
user> (async/<!! c)
3
user>(需要“[clojure.core.async:as async]”
无
用户>(定义c(异步/通道(异步/滑动缓冲区1)))
#'用户/c
用户>(异步/>!!c 1)
真的
用户>(异步/>!!c 2)
真的
用户>(异步/>!!c 3)
真的
用户>(异步)/
这样,在下一个间隔中,只计算最后输入通道的值。

这是从David处获取的:


您可能还想在通道中添加一个重复数据消除传感器。

我需要传递一个函数来捕获args,因为我将它用于输入事件,它传递的是一个可变对象。看起来像是一个更复杂的结构,我无法立即掌握。除了alre,我的方法在某种程度上讲不通吗ady提到了不当行为?我的意思是,这不能很容易地以某种方式解决吗?另请参见:IMO这不是节流,如果生产者和消费者都很快,就不会丢弃消息。答案不完整,但也没有错。一些消费者加上超时和使用
滑动缓冲区
会产生错误完整答案。谢谢!第二个示例性代码示例展示了一个实际应用程序,这将使您的答案成为首选:)还希望看到重复数据消除的实施
(defn my-sender [to-chan values]
  (go-loop [[x & xs] values]
           (>! to-chan x)
           (when (seq xs) (recur xs))))

(defn my-receiver [from-chan f]
  (go-loop []
           (let [res (<! from-chan)]
             (f res)
             (recur))))

(defn setup-and-go []
  (let [in (chan)
        ch (debounce in 4000)
        sender (my-sender in (range 10))
        receiver (my-receiver ch #(log %))])) 
(defn debounce [in ms]
  (let [out (chan)]
    (go-loop [last-val nil
              first-time true]
             (let [val (if (nil? last-val) (<! in) last-val)
                   timer (timeout (if first-time 0 ms))
                   [new-val ch] (alts! [in timer])]
               (condp = ch
                 timer (do (>! out val) (recur nil false))
                 in (recur new-val false))))
    out)) 
user> (require '[clojure.core.async :as async])
nil
user> (def c (async/chan (async/sliding-buffer 1)))
#'user/c
user> (async/>!! c 1)
true
user> (async/>!! c 2)
true
user> (async/>!! c 3)
true
user> (async/<!! c)
3
(defn throttle*
  ([in msecs]
    (throttle* in msecs (chan)))
  ([in msecs out]
    (throttle* in msecs out (chan)))
  ([in msecs out control]
    (go
      (loop [state ::init last nil cs [in control]]
        (let [[_ _ sync] cs]
          (let [[v sc] (alts! cs)]
            (condp = sc
              in (condp = state
                   ::init (do (>! out v)
                            (>! out [::throttle v])
                            (recur ::throttling last
                              (conj cs (timeout msecs))))
                   ::throttling (do (>! out v)
                                  (recur state v cs)))
              sync (if last 
                     (do (>! out [::throttle last])
                       (recur state nil
                         (conj (pop cs) (timeout msecs))))
                     (recur ::init last (pop cs)))
              control (recur ::init nil
                        (if (= (count cs) 3)
                          (pop cs)
                          cs)))))))
    out))

(defn throttle-msg? [x]
  (and (vector? x)
       (= (first x) ::throttle)))

(defn throttle
  ([in msecs] (throttle in msecs (chan)))
  ([in msecs out]
    (->> (throttle* in msecs out)
      (filter #(and (vector? %) (= (first %) ::throttle)))
      (map second))))