2024 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}} 的定义 _替换_ 了 {{my.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
by
参考:https://clojure.atlassian.net/browse/CLJS-2421(由 cemerick 报告)
...