2024 年 Clojure 状态调查! 分享您的想法。

欢迎!请参阅 关于页面 了解更多该如何工作的信息。

0
REPL

大家好,

我有一个脚本,使用 monger 库在 MongoDB 数据库中更新数据。在打开 repl 并复制粘贴代码时,所有的更新都会执行,但是使用 lein run 就无法执行。

相关的代码

(ns covid-data-management.core
(:require [oz.core :as oz]
                  [monger.core :as mg]
                  [monger.collection :as mc]))
(defonce db (mg/get-db (mg/connect) "covid19"))
(def coll "surveys")
(defn update-symptoms []
    (println "In the update-symptoms definitions")
    (map (fn [x]
            (mc/update db coll {} {"$set" {:symptoms ["symptom1" "symptom2"]}}))))

(defn main [& args]
    (update-symptoms))

在 REPL 中粘贴代码确实做到了预期的事情:设置了新的症状。当使用 lein run 运行时,控制台会打印出字符串 "在更新的症状定义中",但是数据库本身并没有改变。

我怀疑这与 Clojure 的无副作用和惰性特性有关,但尚未找到解决方案。非常感谢任何帮助!

谢谢!
j.

2 答案

+3

map 是惰性的。您可能需要在 (doall (map ...)) 调用中包裹 (map ...) 调用,或者使用 mapv(它是急切的)而不是 map 以获得更好的结果。

请注意,在 REPL 中,REPL 的 P(打印)部分将迫使 map 的惰性返回值完全评估以便能够打印。

by
`doall`是一个针对几乎所有与惰性相关的难题的安全万能快速解决方法。不过,如果返回值不重要(只有副作用重要),使用`dorun`将更清晰,而`doseq`可能会有更直接的语法。
by
从Clojure 1.7开始,我可能在这里使用`run!`而不是`doseq`,因为其用法与`map/mapv`相同,但它会更急切,并且会丢弃每个函数调用的结果。
0
by

你的代码中可能有些东西依赖于环境变量。

你的REPL环境是否与你的lein run环境相同?

你可以使用(prn (System/getenv))进行调试

by
两者的环境完全相同...
...