评论由:mfikes
这个点让我在定义什么是应该进行的方面有些犹豫,核心问题是关于{{my.ns/A}}是一个Var还是一个简单的类型。
在编译器状态中,它在 {{:defs}} 下确实会出现,但是被标记为 {{:type true}}。换句话说,仅仅因为它位于 {{:def}} 下并不意味着它是一个 Var。在 Clojure 中,尽管存在可以通过互操作访问的基本构造函数,但实际上并没有创建 Var。证据支持这一论点,即请在 Clojure 中运行 {{(var A)}} 将失败,如果您在 REPL 中使用 {{dir}} 也不会出现 Var——您只看到相关的合成位置和映射工厂 Var。
“它不是一个 Var”的另一个论点是 {{defrecord}} 返回的内容。{{defrecord}} 即使在 Clojure 中也不会返回一个 Var,而是返回一个符号(它的值与其自身相同,就像符号 {{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”的方法,也许可以被清理。