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

"原子地设置名称空间/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/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为真。

所以我认为我必须将我的var引用存储在其他def中,才能按预期进行操作?

0

评论者:thheller

CLJS不使用vars运行时,并且不能像这样进行修改。{{cljs.core/Var}}实例是从该var相关的{{cljs.analyzer}}数据创建的,这些数据存在于CLJ端,因此不能直接通过CLJS修改,除非通过宏。一旦创建了var实例,就可以传递它们,但是{{cljs.core/var}}总是会创建一个新的实例。

0

评论由:baritonehands 发表

在试验了几小时后,我确实发现了这一点。

所以,能否更新alter-meta!文档,以删除对var的提及?此外,如果文档字符串中提到var的行为与Clojure var不同,那会很好。

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