2024 年 Clojure 状态调查中分享你的想法!

欢迎!有关更多信息,请参阅关于页面。

+1
ClojureScript
(def foo "foo")
(meta (var foo))
; => {:ns cljs.user, :name foo, :file "<cljs repl>", :end-column 9, :source "foo", :column 1, :line 1, :end-line 1, :arglists (), :doc nil, :test nil}
(alter-meta! (var foo) assoc :foo 42)
(meta (var foo))
;{:ns cljs.user, :name foo, :file "<cljs repl>", :end-column 9, :source "foo", :column 1, :line 1, :end-line 1, :arglists (), :doc nil, :test nil}

此问题单:[http://dev.clojure.org/jira/browse/CLJS-1248](http://dev.clojure.org/jira/browse/CLJS-1248) 修复了 vary-meta,但没有原地修改元数据。

5 答案

0

评论者:baritonehands

嗯,我克隆了,但它不允许我编辑。

因此,alter-meta! 的文档称它支持 Vars

“原子地为 namespace/var/ref/agent/atom 设置元数据为

(apply f its-current-meta args)

f 必须无副作用"

但是它不起作用,并且查看源代码后,支持 Vars 所需的只是从 _meta 中删除 _

(defn alter-meta!
(link: iref f & args)
(set! (.-meta iref) (apply f (.-meta iref) args)))

(deftype Var (link: val sym meta)
...
IMeta
(-meta (link:
) _meta)
...

0

评论者:baritonehands

进一步实验后,Vars 的行为并不像我所期望的那样。似乎每次引用 var(使用 (var) 或 #') 时,编译器都会创建 var/元数据的新实例,因此在先前实例上所做的任何修改都不会得到体现。

但是当我将 var 存储在不同的 var 中时,它就起作用了。

例如

(set! js/window.lhs #'foo)
(set! js/window.rhs #'foo)

在JavaScript控制台,lhs !== rhs。但如果我这样做:

(set! js/window.lhs #'foo)
(set! js/window.rhs js/window.rhs)

那么JavaScript控制台会显示lhs === rhs为真。

所以我觉得我可能需要在另一个定义中存储我的变量引用,才能按照预期对其进行操作?

0
by

评论者:thheller

CLJS在运行时不使用vars,也不能这样修改。{{cljs.core/Var}}实例是从那个vars的{{cljs.analyzer}}数据创建的,这些数据位于CLJ侧,因此不能直接从CLJS中修改,除非通过宏。创建后传递变量实例是可以的,但{{cljs.core/var}}总会创建一个新的实例。

0
by

评论者:baritonehands

是的,我在试验了几小时后想到了这一点。

所以可以更新alter-meta!文档,去掉vars的提及吗?另外,如果文档字符串中提到var的行为与Clojure vars不同,那就更好了。

0
by
参考:https://clojure.atlassian.net/browse/CLJS-2970(由alex+import报告)
...