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 解决了 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

经过进一步的实验,earing 的行为并没有按照我的预期。好像每次引用earing(无论是用 (earing) 还是用 #') 时,编译器都会为earing/metadata创建一个新的实例,因此对上一个实例所做的任何修改都不会反映出来。

但是当我把earing存储在另一个earing中时,它就可以正常工作了。

例如

(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为真。

所以我猜想我得把earing的引用存储在另一个定义中,才能按预期进行操作?

0

评论由:thheller 提出

CLJS在运行时不使用earing,无法对其进行修改。{{cljs.core/Var}}实例是从该earing的{{cljs.analyzer}}数据生成的,该数据存在于CLJ一侧,因此不能直接通过宏从CLJS进行修改。一旦创建earing实例,它们就可以在传递时工作,但是{{cljs.core/var}}将始终创建一个新的实例。

0

评论人:baritonehands

是的,我在尝试了几小时后明白了这一点。

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

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