在Clojure中收听外部事件

在Clojure中收听外部事件,clojure,Clojure,我有一个clojure函数,它逐行读取文本文件,该文件由外部Python脚本填充。每隔一段时间就会从第0行重新创建并重新填充它 我尝试为Clojure函数创建一个可执行jar文件,但它给了我一个无法解决的Nullpointer异常。因此,我在leinrepl中运行clojure函数,并将其作为python脚本并行运行 我试图包含一个函数来监视文件是否被重新创建,但在while循环中,它似乎没有调用回调 我的clojure函数 (defn test [n] (def stop-watch (s

我有一个clojure函数,它逐行读取文本文件,该文件由外部Python脚本填充。每隔一段时间就会从第0行重新创建并重新填充它

我尝试为Clojure函数创建一个可执行jar文件,但它给了我一个无法解决的Nullpointer异常。因此,我在
leinrepl
中运行clojure函数,并将其作为python脚本并行运行

我试图包含一个函数来监视文件是否被重新创建,但在while循环中,它似乎没有调用回调

我的clojure函数

(defn test [n]
  (def stop-watch (start-watch 
                [{ :path "/home/project/"
                  :event-types [:create :modify]
                  :callback (fn [event filename]
                    (when (and (.contains filename "data.txt") (= event :create))
                     (def cycle 0))
                  }]))

  (while (< cycle n)
   (let [data (read-data cycle)
         data (process-data data)]
   (def cycle (inc cycle))
))


(defn read-data [cycle]
 (loop []
  (let [
      path "/home/project/data.txt"
      Example (when (.exists (clojure.java.io/file path))
       (with-open [rdr (clojure.java.io/reader path)]
       (reduce conj [] (line-seq rdr))))
      data (map clojure.edn/read-string Example)]
      (if (> (count data) cycle)
        (nth data cycle)
        (do
          (Thread/sleep 2)
          (recur)))))
)

(defn测试[n]
(def秒表(起动表
[{:path”/home/project/“
:事件类型[:创建:修改]
:回调(fn[事件文件名]
(和(.包含文件名“data.txt”)(=事件:创建)时)
(def循环0)
}]))
(同时(<循环n)
(let[数据(读取数据周期)
数据(过程数据)]
(def循环(inc循环))
))
(defn读取数据[循环]
(循环[]
(让[
路径“/home/project/data.txt”
示例(当(.exists(clojure.java.io/file path))存在时)
(打开[rdr(clojure.java.io/reader路径)]
(减少联合[](行顺序rdr)))
数据(map clojure.edn/read-string示例)]
(如果(>(计数数据)周期)
(第n个数据周期)
(做
(线程/睡眠2)
((""))(重复"""")
)
当external data.txt文件复位时,clojure函数如何知道它应该复位循环计数?我不希望它总是返回最后一行,而是返回当前循环运行的确切行-因此,如果它还不在那里,它应该等到它在那里


有什么建议吗?

我快速尝试了一下,希望它能对您有所帮助:这个简单的示例将
start watch
返回的函数引用放入一个atom中,这样您就可以保留对它的引用并在其他地方使用,这样我们就可以从
调用它(停止监视器)
以交互方式运行。我在emacs with CIDER中的REPL上运行了这两个函数,似乎工作正常。我用
注释了几行,以便我可以从编辑器中对它们进行评估

演示函数需要一个小文件(这样就可以用
slurp
在内存中读取整个文件,并需要每行使用
:amount
键的哈希映射,然后将它们相加。还有一个计数器,可以用于某些逻辑(我只将其用于显示)。这样做的目的是,您将对事件做出反应,而不是忙于等待(例如,
线程/睡眠
)等待创建/更新文件

(ns watchtest.core
(:需要[clojure-watch.core:参考[start watch]]))
(def计数器(原子0))
(def手表止动器(atom(fn[](println“尚未启动!”))
(defn进程文件[事件文件名]
(在“事件”事件之后打印“处理”文件名。”)
(println“这是事件”(swap!counter inc))
(->>(slurp文件名)
(clojure.字符串/拆分行)
(地图读取字符串)
(map:amount);;假设它是一系列带有:amount列的映射
(减少+)
(打印“总金额:))
(defn启动监视器[]
(让[watch props{:path”/tmp/watchtest/files)
:事件类型[:创建:修改]
:引导(fn[path](println“开始观察”路径))
:回调进程文件
:选项{:递归真}
停止fn(开始观看[观看道具])
(重置!手表止动器停止fn)))
(defn停止监视器[]
(打印“停止监视器”)
(@watchstopper))
(启动监视器)
(停止监视器)
(定义-主参数[&args]
(启动监视器)
(defn创建演示文件[]
(让[内容(->>)(范围10 20)
(映射#(哈希映射:数量%)
(地图街)
(插入“\n”)
(减少str))]
(spit“/tmp/watchtest/files/demo.txt”内容)
(创建演示文件)
以下是
lein repl
中的互动会话示例作为参考:

$ lein repl
nREPL server started on port 43105 on host 127.0.0.1 - nrepl://127.0.0.1:43105
REPL-y 0.4.3, nREPL 0.6.0
Clojure 1.10.0
OpenJDK 64-Bit Server VM 11.0.7+10-post-Ubuntu-2ubuntu218.04
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

watchtest.core=> (create-demo-file)
nil
watchtest.core=> (start-monitor)
Starting to watch /tmp/watchtest/files
#object[clojure_watch.core$start_watch$close_watcher__209 0x2ecd9518 "clojure_watch.core$start_watch$close_watcher__209@2ecd9518"]
watchtest.core=> (create-demo-file)
nil
Processing /tmp/watchtest/files/demo.txt after a :modify event.
This is event # 1
Total amount: 145
watchtest.core=> (create-demo-file)
nilProcessing /tmp/watchtest/files/demo.txt after a :modify event.
This is event # 2
Total amount: 145
watchtest.core=> (stop-monitor)
Stopping monitor
nil
watchtest.core=> (create-demo-file)
nil
watchtest.core=> Bye for now!

我对此进行了快速尝试,希望它能对您有所帮助:这个简单的示例将
start watch
返回的函数引用放入atom中,这样您就可以保留对它的引用并在其他地方使用它,这样我们就可以从
调用它(停止监视器)
以交互方式运行。我在emacs with CIDER中的REPL上运行了这两个函数,似乎工作正常。我用
注释了几行,以便我可以从编辑器中对它们进行评估

演示函数需要一个小文件(这样就可以用
slurp
在内存中读取整个文件,并需要每行使用
:amount
键的哈希映射,然后将它们相加。还有一个计数器,可以用于某些逻辑(我只将其用于显示)。这样做的目的是,您将对事件做出反应,而不是忙于等待(例如,
线程/睡眠
)等待创建/更新文件

(ns watchtest.core
(:需要[clojure-watch.core:参考[start watch]]))
(def计数器(原子0))
(def手表止动器(atom(fn[](println“尚未启动!”))
(defn进程文件[事件文件名]
(在“事件”事件之后打印“处理”文件名。”)
(println“这是事件”(swap!counter inc))
(->>(slurp文件名)
(clojure.字符串/拆分行)
(地图读取字符串)
(map:amount);;假设它是一系列带有:amount列的映射
(减少+)
(打印“总金额:))
(defn启动监视器[]
(让[watch props{:path”/tmp/watchtest/files)
:事件类型[:创建:修改]
:引导(fn[path](println“开始观察”路径))
:回调进程文件
:选项{:递归真}
停止fn(开始观看[观看道具])
(重置!看