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))

然而,当我们查看给定的 this: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编译器以支持我之前的评论中链接的两种用法(包括我的OP)。

如果这种情况在可预见的未来不会发生,我可能会改进Eastwood linter以清楚地告知如何改进"extend-type/extend-protocol"的使用。
我认为这不是编译器的问题,而是关于"extend-type"要支持什么语法的问题。
目前这个问题有确切的答案吗?
我认为extend-type目前期望的是一个类,而不是一个evals为类的东西。
...