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运行时,控制台打印出字符串"In the update-symptoms definitions",但数据库本身并没有改变。

我怀疑这与Clojure的no-side-effects(无副作用)和lazy(惰性)功能有关,但还没有找到解决方案。任何帮助都欢迎!

谢谢,
j.

2 答案

+3

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

请注意,在REPL中,REPL的P(打印)部分将强制从map获取的懒性返回值被完全求值,以便可以打印。

`doall` 是一个安全的多用途快速修复方法,适用于几乎任何与懒惰有关的问题。但是,如果返回值不重要(只有副作用很重要),则 `dorun` 可能更清晰,而 `doseq` 可能更直接、更符合语言习惯。
从Clojure 1.7开始,我可能会在这里使用run!而不是doseq,因为它与map/mapv的使用方式完全相同,但它是 eager 的,并且丢弃每个函数调用的结果。
0

您的代码中的某些内容可能依赖于环境变量。

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

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

两个环境完全相同...
...