参与2024年Clojure调查,分享您的看法!2024 States of Clojure调查!

欢迎!请查看关于页面以获取更多关于此功能的信息。

0
ClojureScript
两个命名空间


(ns my.ns)

(defrecord A [foo bar])

(defn make-a [foo bar]
  (A. foo bar))



(ns other.ns
  (:require [my.ns :refer (A)]))

(println (my.ns/A. 1 2) (my.ns/make-a 1 2))

(defrecord A [baz quux])

(println (my.ns/A. 1 2) (my.ns/make-a 1 2))


加载{{other.ns}}产生以下输出


#my.ns.A{:foo 1, :bar 2} #my.ns.A{:foo 1, :bar 2}
#my.ns.A{:baz 1, :quux 2} #my.ns.A{:baz 1, :quux 2}


替换{{other.ns.A}}的定义

4 个回答

0

评论由:cemerick

这可能是一个CLJS-1558的重复...

0

评论由:mfikes

这个问题与CLJS-1558有相似之处,因为编译器实际上允许你重新{{def}}一个引用的Var。也许这两个问题都应该导致编译器错误,就像Clojure中发生的那样。

0
评论由: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”的方法,也许可以被清理。
0
参考:https://clojure.atlassian.net/browse/CLJS-2421(由 cemerick 报告)
...