首先,我没有CS的经验,而Clojure是我的第一语言,所以请原谅如果以下问题有解决方案,这对于程序员来说是很明显的.
问题的摘要如下:一个人需要在未知时间随意创建未知但符号的原子.我的方法围绕a)临时存储原子的名称作为原子本身的字符串; b)将这些字符串更改为具有函数的符号; c)使用函数添加和创建新原子.问题与步骤"c"有关:调用函数不会创建新原子,但使用它的主体会创建它们.
REPL中采取的所有步骤如下(注释遵循代码块):
user=> (def atom-pool
#_=> (atom ["a1" "a2"]))
#'user/atom-pool
Run Code Online (Sandbox Code Playgroud)
'atom-pool是将中间原子作为字符串存储的原子.
user=> (defn atom-symbols []
#_=> (mapv symbol (deref atom-pool)))
#'user/atom-symbols
user=> (defmacro populate-atoms []
#_=> (let [qs (vec (remove #(resolve %) (atom-symbols)))]
#_=> `(do ~@(for [s qs]
#_=> `(def ~s (atom #{}))))))
#'user/populate-atoms
Run Code Online (Sandbox Code Playgroud)
'populate-atoms是定义那些原子的宏.注意,目的(remove #(resolve %) (atom-symbols))是仅创建尚未存在的原子.'atom-symbols读取'atom-pool并将其内容转换为符号.
user=> (for [s ['a1 'a2 'a-new]]
#_=> (resolve s))
(nil nil nil)
Run Code Online (Sandbox Code Playgroud)
这里确认到目前还没有'a1','a2','a-new'原子.
user=> (defn new-atom [a]
#_=> (do
#_=> (swap! atom-pool conj a)
#_=> (populate-atoms)))
#'user/new-atom
Run Code Online (Sandbox Code Playgroud)
'new-atom是函数,它首先将新的to-be atom作为字符串添加到`atom-pool.然后'populate-atoms从'atom-symbols函数创建所有原子.
user=> (for [s ['a1 'a2 'a-new]]
#_=> (resolve s))
(#'user/a1 #'user/a2 nil)
Run Code Online (Sandbox Code Playgroud)
在这里我们看到'a1'a2是clojure.lang.Var$Unbound通过定义一个函数而创建的,为什么?
user=> (new-atom "a-new")
#'user/a2
user=> (for [s ['a1 'a2 'a-new]]
#_=> (resolve s))
(#'user/a1 #'user/a2 nil)
Run Code Online (Sandbox Code Playgroud)
召唤(new-atom "a-new")并没有创造出'新原子!
user=> (do
#_=> (swap! atom-pool conj "a-new")
#_=> (populate-atoms))
#'user/a-new
user=> (for [s ['a1 'a2 'a-new]]
#_=> (resolve s))
(#'user/a1 #'user/a2 #'user/a-new)
user=>
Run Code Online (Sandbox Code Playgroud)
在这里,我们看到明确诉诸'新原子的身体'确实创造了'一个新原子'.'a-new是一种类型clojure.lang.Atom,但'a1和'a2被跳过,因为已经存在于命名空间中clojure.lang.Var$Unbound.
感谢任何帮助如何让它工作!
编辑:注意,这是一个例子.在我的项目中,'atom-pool实际上是一组地图(带有地图的原子).这些地图有键{:name val}.如果添加了一个新映射,那么我通过解析它的:name键为该映射创建一个相应的原子.
"这个问题的摘要如下:一个人需要在未知的时间随意创建未知但符号的原子."
这听起来像是寻找问题的解决方案.我通常建议你尝试另一种实现任何实际功能的方法而不在运行时生成变量,但如果必须,你应该使用intern并省略宏的东西.
你不能用宏解决这个问题,因为宏在编译时被扩展,这意味着在
(defn new-atom [a]
(do
(swap! atom-pool conj a)
(populate-atoms)))
Run Code Online (Sandbox Code Playgroud)
populate-atoms只扩展一次; 当(defn new-atom ...)窗体被编译,但你试图改变其扩张时new-atom被调用(这必然发生后).
| 归档时间: |
|
| 查看次数: |
138 次 |
| 最近记录: |