在不触及元数据的情况下更改 Clojure var 的值
Change the value of a Clojure var without touching the metadata
我一直在假设 var 的元数据是“稳定的”,也就是说,我可以在不更改 var 的元数据的情况下更改 var 的值。现在我发现我的理解有问题。代码:
(def ^{:Metadata "metaA"} A 1) ;; Define A with value 1 and metadata.
=> #'thic.core/A
(def ^{:Metadata "metaB"} B 2) ;; Define B with value 2 and metadata.
=> #'thic.core/B
A ;; A's value is 1.
=> 1
B ;; B's value is 2.
=> 2
(meta (var A))
=>
{:Metadata "metaA", ;; A has the defined metadata.
:line 1,
:column 1,
:file "C:\Users\Joe User\AppData\Local\Temp\form-init2487748963910096550.clj",
:name A,
:ns #object[clojure.lang.Namespace 0x147c445 "thic.core"]}
(meta (var B))
=>
{:Metadata "metaB", ;; So does B.
:line 1,
:column 1,
:file "C:\Users\Joe User\AppData\Local\Temp\form-init2487748963910096550.clj",
:name B,
:ns #object[clojure.lang.Namespace 0x147c445 "thic.core"]}
(def B A) ;; Give B A's value,
=> #'thic.core/B
A
=> 1
B ;; which it now has,
=> 1
(meta (var B)) ;; and B's previously-defined metadata is gone.
=>
{:line 1,
:column 1,
:file "C:\Users\Joe User\AppData\Local\Temp\form-init2487748963910096550.clj",
:name B,
:ns #object[clojure.lang.Namespace 0x147c445 "thic.core"]}
(meta (var A)) ;; A's remains unchanged.
=>
{:Metadata "metaA",
:line 1,
:column 1,
:file "C:\Users\Joe User\AppData\Local\Temp\form-init2487748963910096550.clj",
:name A,
:ns #object[clojure.lang.Namespace 0x147c445 "thic.core"]}
有没有一种方法可以在不清除 B 中的元数据的情况下将 A 的值赋给 B?
或者我只是不明白“绑定”和“赋值”的区别?
Clojure 实战第 2 版 说“当从具有元数据的值创建新值时,元数据将被复制到新数据中。” (第 57 页)我的示例不是 创建 新值。那是问题所在吗?我仍然想修改变量的值而不修改其元数据。
我谦卑地恳求你,ClojureGods。
alter-var-root
可以做到。
-------------------------
clojure.core/alter-var-root
([v f & args])
Atomically alters the root binding of var v by applying f to its
current value plus any args
例如:
; Clojure 1.10.3
(def ^{:Metadata "metaA"} A 1)
; #'user/A
(def ^{:Metadata "metaB"} B 2)
; #'user/B
A
; 1
B
; 2
(meta #'A)
; {:Metadata "metaA", :line 1, :column 1, :file "NO_SOURCE_PATH", :name A, :ns #object[clojure.lang.Namespace 0x2189e7a7 "user"]}
(meta #'B)
; {:Metadata "metaB", :line 1, :column 1, :file "NO_SOURCE_PATH", :name B, :ns #object[clojure.lang.Namespace 0x2189e7a7 "user"]}
(alter-var-root #'B (constantly A))
; 1
B
; 1
(meta #'B)
; {:Metadata "metaB", :line 1, :column 1, :file "NO_SOURCE_PATH", :name B, :ns #object[clojure.lang.Namespace 0x2189e7a7 "user"]}
我一直在假设 var 的元数据是“稳定的”,也就是说,我可以在不更改 var 的元数据的情况下更改 var 的值。现在我发现我的理解有问题。代码:
(def ^{:Metadata "metaA"} A 1) ;; Define A with value 1 and metadata.
=> #'thic.core/A
(def ^{:Metadata "metaB"} B 2) ;; Define B with value 2 and metadata.
=> #'thic.core/B
A ;; A's value is 1.
=> 1
B ;; B's value is 2.
=> 2
(meta (var A))
=>
{:Metadata "metaA", ;; A has the defined metadata.
:line 1,
:column 1,
:file "C:\Users\Joe User\AppData\Local\Temp\form-init2487748963910096550.clj",
:name A,
:ns #object[clojure.lang.Namespace 0x147c445 "thic.core"]}
(meta (var B))
=>
{:Metadata "metaB", ;; So does B.
:line 1,
:column 1,
:file "C:\Users\Joe User\AppData\Local\Temp\form-init2487748963910096550.clj",
:name B,
:ns #object[clojure.lang.Namespace 0x147c445 "thic.core"]}
(def B A) ;; Give B A's value,
=> #'thic.core/B
A
=> 1
B ;; which it now has,
=> 1
(meta (var B)) ;; and B's previously-defined metadata is gone.
=>
{:line 1,
:column 1,
:file "C:\Users\Joe User\AppData\Local\Temp\form-init2487748963910096550.clj",
:name B,
:ns #object[clojure.lang.Namespace 0x147c445 "thic.core"]}
(meta (var A)) ;; A's remains unchanged.
=>
{:Metadata "metaA",
:line 1,
:column 1,
:file "C:\Users\Joe User\AppData\Local\Temp\form-init2487748963910096550.clj",
:name A,
:ns #object[clojure.lang.Namespace 0x147c445 "thic.core"]}
有没有一种方法可以在不清除 B 中的元数据的情况下将 A 的值赋给 B?
或者我只是不明白“绑定”和“赋值”的区别?
Clojure 实战第 2 版 说“当从具有元数据的值创建新值时,元数据将被复制到新数据中。” (第 57 页)我的示例不是 创建 新值。那是问题所在吗?我仍然想修改变量的值而不修改其元数据。
我谦卑地恳求你,ClojureGods。
alter-var-root
可以做到。
-------------------------
clojure.core/alter-var-root
([v f & args])
Atomically alters the root binding of var v by applying f to its
current value plus any args
例如:
; Clojure 1.10.3
(def ^{:Metadata "metaA"} A 1)
; #'user/A
(def ^{:Metadata "metaB"} B 2)
; #'user/B
A
; 1
B
; 2
(meta #'A)
; {:Metadata "metaA", :line 1, :column 1, :file "NO_SOURCE_PATH", :name A, :ns #object[clojure.lang.Namespace 0x2189e7a7 "user"]}
(meta #'B)
; {:Metadata "metaB", :line 1, :column 1, :file "NO_SOURCE_PATH", :name B, :ns #object[clojure.lang.Namespace 0x2189e7a7 "user"]}
(alter-var-root #'B (constantly A))
; 1
B
; 1
(meta #'B)
; {:Metadata "metaB", :line 1, :column 1, :file "NO_SOURCE_PATH", :name B, :ns #object[clojure.lang.Namespace 0x2189e7a7 "user"]}