请在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是懒的。您可能需要在(doall (map ...))或使用mapv(它是急切的)而不是map的调用中包装(map ...)调用以获得更好的结果。

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

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

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

您的 REPL 环境与您的 lein run 环境相同吗?

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

两者...的环境变量完全相同...
...