Clojure 跨多个名称空间共享状态
在编写我的第一个Clojure程序时,我偶然发现了以下任务,我无法解决:Clojure 跨多个名称空间共享状态,clojure,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首先被调用,但随后还没
(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
数据。我不知道如何避开这个问题:(
- 我无法使用
重新定义def
,得到错误data
。也许我应该在这里使用ref/atom/agent(还没有使用它们,但我现在正在研究..)java.lang.IllegalStateException:数据已经引用了命名空间中的#core/data:calc
我如何在
calc
中引用和变异core/data
,就好像它是在那里定义的一样?在我看来,你这样做完全是错误的,可能对你应该如何在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))
在我看来,您这样做是完全错误的,并且可能对应该如何在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))
在我看来,您这样做是完全错误的,并且可能对应该如何在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))
在我看来,您这样做是完全错误的,并且可能对应该如何在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))
作为RedDeckWins建议的扩展,如果您希望让突变发生在
核心
中,并避免将数据
传递给计算
中的每个函数,您可以在计算
中创建一个动态变量。更新数据
中的第一个语句,您将传递的值绑定到动态变量calc
中的oncerned函数总是引用动态变量
(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")))
也就是说,我仍然建议将
应用程序数据
传递给calc
中的每个函数。这样,每个函数都可以增量修改应用程序数据
,并且操作
可以返回最终状态。为了支持突变并避免将状态传递给每个函数,您需要用atom替换动态变量。calc
中的原子将在本地使用,它的值将从操作中返回。我会避免这种情况。作为RedDeckWins建议的扩展,如果您希望让突变发生在核心
中,并避免将数据
传递给calc
中的每个函数,您可以在ca>中创建一个动态变量lc
。在更新数据
中的第一条语句中,您将把传入的值绑定到动态变量。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")))
也就是说,我仍然建议将应用程序数据
传递给calc
中的每个函数。这样,每个函数都可以增量修改应用程序数据
,并且操作
可以返回最终状态。为了支持突变并避免将状态传递给每个函数,您需要用atom替换动态变量。calc
中的原子将在本地使用,它的值将从操作中返回。我会避免这种情况。作为RedDeckWins建议的扩展,如果您希望让突变发生在核心
中,并避免将数据
传递给calc
中的每个函数,您可以在ca>中创建一个动态变量lc
。在更新数据
中的第一条语句中,您将把传入的值绑定到动态变量。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")))
也就是说,我仍然建议将应用程序数据
传递给calc
中的每个函数。这样,每个函数都可以增量修改应用程序数据
,并且操作
可以返回最终状态。为了支持突变并避免将状态传递给每个函数,您需要用atom替换动态变量。calc
中的原子将在本地使用,它的值将从操作中返回。我会避免这种情况。作为RedDeckWins建议的扩展,如果您希望让突变发生在核心
中,并避免将数据
传递给calc
中的每个函数,您可以在ca>中创建一个动态变量lc
。在更新数据
中的第一条语句中,您将把传入的值绑定到动态变量。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")))
也就是说,我仍然建议将应用程序数据
传递给calc
中的每个函数。这样,每个函数都可以增量修改应用程序数据
,并且操作
可以返回最终状态。为了支持突变并避免将状态传递给每个函数,您需要用atom替换动态变量。calc
中的atom将在本地使用,其值将从操作中返回。我会避免这种情况。谢谢你的回答。也许我过于简化了我的示例。实际上,更新数据函数包括许多其他函数,这些函数都依赖于数据。因此,由于我只处理一组数据,而不是传递数据拥有整个链我希望能够从代码中的任何地方引用它,这就是我希望引用它的原因。是否存在这样的用例:人们更喜欢这种“全局状态”行为而不是“传递状态”对于几乎所有的函数?例如,假设数据是核心
ns中的一个中心配置,我想在选项菜单
ns中对其进行变异。仔细想想,我喜欢这种变异(交换!
)只出现在核心
名称空间中,因为代码中其他地方没有副作用