定期调用Clojure中的函数

 ARUAN地盘_740 发布于 2023-01-30 19:42

我正在寻找一种在Clojure中定期调用函数的简单方法.

JavaScript setInterval有我想要的那种API.如果我在Clojure中重新构想它,它看起来像这样:

(def job (set-interval my-callback 1000))

; some time later...

(clear-interval job)

出于我的目的,我不介意这是创建一个新线程,在线程池或其他东西中运行.时机也是准确的并不重要.事实上,提供的时间段(以毫秒为单位)可能只是一个呼叫结束和下一个呼叫开始之间的延迟.

6 个回答
  • 我对此进行了编码,其界面略微修改,而不是原始问题中指定的界面.这就是我想出来的.

    (defn periodically [fn millis]
      "Calls fn every millis. Returns a function that stops the loop."
      (let [p (promise)]
        (future
          (while
              (= (deref p millis "timeout") "timeout")
            (fn)))
        #(deliver p "cancel")))
    

    欢迎反馈.

    2023-01-30 19:44 回答
  • 如果你想要非常简单

    (defn set-interval [callback ms] 
      (future (while true (do (Thread/sleep ms) (callback)))))
    
    (def job (set-interval #(println "hello") 1000))
     =>hello
       hello
       ...
    
    (future-cancel job)
     =>true
    

    再见.

    2023-01-30 19:44 回答
  • 最简单的方法是在一个单独的线程中有一个循环.

    (defn periodically
      [f interval]
      (doto (Thread.
              #(try
                 (while (not (.isInterrupted (Thread/currentThread)))
                   (Thread/sleep interval)
                   (f))
                 (catch InterruptedException _)))
        (.start)))
    

    您可以使用Thread.interrupt()以下命令取消执

    (def t (periodically #(println "Hello!") 1000))
    ;; prints "Hello!" every second
    (.interrupt t)
    

    你甚至可以future用来包裹循环并future-cancel阻止它.

    2023-01-30 19:45 回答
  • 另一种选择是使用java.util.Timer的schedualeAtFixedRate方法

    编辑 - 在单个计时器上复用任务,并停止单个任务而不是整个计时器

    (defn ->timer [] (java.util.Timer.))
    
    (defn fixed-rate 
      ([f per] (fixed-rate f (->timer) 0 per))
      ([f timer per] (fixed-rate f timer 0 per))
      ([f timer dlay per] 
        (let [tt (proxy [java.util.TimerTask] [] (run [] (f)))]
          (.scheduleAtFixedRate timer tt dlay per)
          #(.cancel tt))))
    
    ;; Example
    (let [t    (->timer)
          job1 (fixed-rate #(println "A") t 1000)
          job2 (fixed-rate #(println "B") t 2000)
          job3 (fixed-rate #(println "C") t 3000)]
      (Thread/sleep 10000)
      (job3) ;; stop printing C
      (Thread/sleep 10000)
      (job2) ;; stop printing B
      (Thread/sleep 10000)
      (job1))
    

    2023-01-30 19:45 回答
  • 这就是我如何使用停止通道执行core.async版本.

    (defn set-interval
      [f time-in-ms]
      (let [stop (chan)]
        (go-loop []
          (alt!
            (timeout time-in-ms) (do (<! (thread (f)))
                                     (recur))
            stop :stop))
        stop))
    

    和用法

    (def job (set-interval #(println "Howdy") 2000))
    ; Howdy
    ; Howdy
    (close! job)
    

    2023-01-30 19:45 回答
  • Clojure还有很多调度库:(从简单到非常先进)

    在-AT

    chime (core.async集成)

    单调

    石英岩

    直接来自at-at的github主页的例子:

    (use 'overtone.at-at)
    (def my-pool (mk-pool))
    (let [schedule (every 1000 #(println "I am cool!") my-pool)]
      (do stuff while schedule runs)
      (stop schedule))
    

    使用(every 1000 #(println "I am cool!") my-pool :fixed-delay true),如果你想任务结束之间一秒钟的延迟和明年的开始,而不是两次启动之间.

    2023-01-30 19:47 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有