跨多个名称空间共享状态

时间:2015-08-20 12:50:13

标签: clojure

编程我的第一个Clojure程序我偶然发现了以下任务,我无法解决:

(ns core
  (:require [calc]))

(def data 1) 
(calc/updatedata)
data 
;; should return 2

(ns calc)
(refer 'core :only '[data]) 
(defn updatedata []
  (def data (+ 1 data)))

现在我有两个问题:

  • 由于core需要calc,首先会调用calc,但之后还没有符号data。我不知道怎么解决这个问题:(
  • 我无法使用data重新定义def,收到错误java.lang.IllegalStateException: data already refers to #'core/data in namespace: calc。也许我应该在这里使用ref / atom / agent(还没有和那些人一起工作但是我现在正在研究它......)?

如何在core/data中引用和变异calc,就像在那里定义一样?

2 个答案:

答案 0 :(得分:2)

作为RedDeckWins提议的扩展,如果您希望在core中发生变异并避免将data传递给calc中的每个函数,您可以在calc中创建动态变量{1}}。在update-data中的第一个语句,您将传入的值绑定到动态var。 calc中所有相关函数总是引用动态变量。

(ns noob-1.calc)

(def ^:dynamic *app-data* {:val false})

(defn action-1 []
  (println "action-1 data - " *app-data*))

(defn action-2 []
  (println "action-2 data - " *app-data*))

(defn actions [data]
  (binding [*app-data* data]
    (println "actions data - " *app-data*)
    (action-1)
    (action-2)
    (assoc *app-data* :val "2")))
(ns noob-1.core
  :require [noob-1.calc :as calc])

(def app-data (atom {:val "1"}))

(defn calc-stuff []
  (swap! app-data calc/actions))

尽管如此,我仍然建议将app-data传递给calc中的每个功能。这样,每个函数都可以逐步修改app-dataactions可以返回最终状态。为了支持突变并避免将状态传递给每个函数,您需要用原子替换动态var。 calc中的原子将在本地使用,其值从actions返回。我会避免这种情况。

答案 1 :(得分:1)

在我看来,你完全错误地做了这个,并且可能对你应该如何在Clojure中编程有一个根本的误解,但是我们走了。

(ns clojure-scratch.core
  (:require [clojure-scratch.calc :as calc]))

(def data (atom 1))

(swap! data calc/update-data)

在另一个档案中

(ns clojure-scratch.calc)

(defn update-data [n]
  (inc n))