_由:mfikes_
我在确定应该发生的情况时有些纠结,核心问题在于 {{my.ns/A}} 是一个 Var 还是仅仅是一种类型。
在编译状态中,它在 {{:defs}} 下出现,但被标记为 {{:type true}}。换句话说,仅仅因为它在 {{:def}} 下面并不意味着它就是一个 Var。在 Clojure 中,尽管存在一个可以通过互操作访问的底层构造函数,但没有创建实际的 Var。(这一说法的证据是,{{(var A)}} 在 Clojure 中会失败,并且在 REPL 中使用 {{dir}} 时不会出现 Var——你只能看到相关的合成位置和映射工厂 Var。)
另一个证据表明“它不是一个 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”的方法,可能可以清理。