2024年Clojure状态调查!中分享你的想法。

欢迎!请查看《关于》页面以获取更多关于如何使用本站的信息。

0
编译器

以下是一个有效的Clojure代码(注意extend-type (class (log-window-proxy nil)),而不是引用类字面量)

(defn- log-window-proxy [state]
  (proxy [javax.swing.JTextArea clojure.lang.IDeref] []
    (deref [] state)
    (scrollRectToVisible [rect]
      (if @(:auto-scroll? state)
        (proxy-super scrollRectToVisible rect)))))

(defprotocol LogWindow
  (log   [this message])
  (clear [this]))

(extend-type (class (log-window-proxy nil))
  LogWindow
  (log [this message]
    (println "message" message))
  (clear [this]
    nil))

:tag元数据的形式似乎有些奇怪(因为它仍然是一系列调用的链接,而不是类字面量)

(-> (extend-type (class (log-window-proxy nil))
      LogWindow
      (log [this message]
        (println "message" message))
      (clear [this]
        nil)) quote macroexpand last :log second ffirst meta)
;; => {:tag (class (log-window-proxy nil))}

所以,:tag看起来像是一个函数调用。编译器最终会调用(class (log-window-proxy ...来获取一个可以用作类型提示的类吗?

否则,我会担心此:tag元数据无效,这可能导致反射警告,并且还可能混淆第三方工具。

1 个回答

+1

被选中
 
最佳答案

你为什么说这是有效的Clojure代码?

文档字符串暗示,预计t将是一个类(不是评估为类的东西)。它是否也在所引用的案例中工作可能是微不足道的 - 我不知道你能否期望那样工作。你提出的问题进一步证明了这一点。"extend-type"是"extend"的帮助包装器,你可以在这种特殊情况下直接使用"extend"(一个函数)来获取评估后的类以及你寻求的具体类型提示,如果它们不同。
感谢指出`extend`可以是一个更好的选择。这可能很有趣,可以对Clojure编译器进行改进,以支持像我先前评论中链接的两个 ones(加上我的OP)的使用。

如果这将在可预见的未来发生,我可能会改进Eastwood linter,以清楚地通知如何改进“extend-type/extend-protocol”的使用。
我认为这并不是编译器的问题,而是一个关于 `extend-type` 支持何种语法的疑问。
目前对于这个问题是否有明确的答案呢?
我认为,目前 extend-type 预期的是一个类,而不是(eval)为类的任何东西。
...