_评论由:mfikes_
我对如何定义底层的行为感到有些困惑,核心问题在于 {{my.ns/A}} 是 Var 还是只是一个类型。
在编译器状态下,它会在 {{:defs}} 下显示,但被标记为 {{:type true}}。 (换句话说,仅仅因为它位于 {{:def}} 下面,并不意味着它是一个 Var。) 在 Clojure 中,尽管存在可以通過互操作性访问的基本构造函数,但实际上并没有创建任何 Var。 (支持这一说法的证据是在 Clojure 中 {{(var A)}} 会失败,如果你在 REPL 中使用 {{dir}},将不会出现任何 Var——你只能看到相关的自生成位置和映射工厂 Vars。
"它不是一个 Var" 的另一个论据是 {{defrecord}} 返回的内容。 {{defrecord}} 并不返回一个 Var (即使是在 Clojure 中),而是返回一个符号(它投射为自己,类似于符号 {{java.lang.String}})。
如果你同意基本构造函数不是 Var 的观点,那么可能有些东西可以被清理(修复 ClojureScript 中的 {{dir}},以及可能使 {{var}} 在应用于类型时出现故障)。
此外,如果你同意它不是 Var 的观点,那么你可能会认为 {{import}} 是合适的,而 {{require}} 则不合适。受到
http://puredanger.github.io/tech.puredanger.com/2010/06/30/using-records-from-a-different-namespace-in-clojure/ 的启发,这种变化似乎工作得很好
(ns my.ns)
(defrecord A [foo bar])
(ns other.ns
(:require [my.ns])
(:import (my.ns.A)))
(println (my.ns.A. 1 2) (my.ns/->A 1 2))
(defrecord A [baz quux])
(println (my.ns.A. 1 2) (my.ns/->A 1 2))
(println (A. 3 4) (->A 3 4))
得到以下结果
cljs.user=> (require 'other.ns)
#my.ns.A{:foo 1, :bar 2} #my.ns.A{:foo 1, :bar 2}
#my.ns.A{:foo 1, :bar 2} #my.ns.A{:foo 1, :bar 2}
#other.ns.A{:baz 3, :quux 4} #other.ns.A{:baz 3, :quux 4}
nil
我不喜欢的一点是,你必须写成 {{(:import (my.ns.A))}} 而不是 {{(:import (my.ns A))},但也许这只是一个小奇癖,如果采取“不是一个 Var”的方法,也许可以清理。