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

"原子的将命名空间/vars/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/metadata 创建一个新实例,因此对先前的任何修改都不会反映出来。

但是当我在另一个 var 中存储 var 时,它会工作。

例如

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

在JS控制台,lhs !== rhs。但如果我做

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

那么JS控制台会说lhs === rhs为真。

所以我猜我必须将我的变量引用保存在另一个def中,以便按预期操作它?

0
by

评论者:thheller

CLJS在运行时不使用vars,也不能以此方式修改。{{cljs.core/Var}}实例是从该vars的{{cljs.analyzer}}数据创建的,这些数据存在于CLJ侧,因此不能直接从CLJS修改,除非通过宏。一旦创建了vars实例,这样做是有效的,但是{{cljs.core/var}}总是会在其他情况下创建一个新的实例。

0
by

评论者:baritonehands

是的,我在几个小时的努力之后才发现这一点。

所以,是否可以将alter-meta!文档更新以移除对vars的提及?此外,如果文档字符串中提及var,最好指出它的行为与Clojure vars不同。

0
by
参考:https://clojure.atlassian.net/browse/CLJS-2970 (由alexiimport提交)
...