请在 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 的:标签元数据时,它似乎具有某种不寻常的形式(因为它仍然是一连串的调用,而不是类字面量)。

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

所以,:标签看起来像一个函数调用。编译器最终是否会调用 (class (log-window-proxy ...)

否则,我会担心这个:标签元数据是无效的,这可能会导致反射警告,并且还会使第三方工具更加困惑。

1 个答案

+1

被选中
 
最佳答案

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

by
文档字符串让我认为 t 应该是一个类(而不仅仅是评估为类的某些内容)。它是否也适用于引证的情况并不重要——我不知道你是否应该期待它这样做。你提出的这个问题 further 强化了这一点。extend-type 是 extend 的辅助包装器,如果你在这个特殊情况下希望获取评估过的类以及你寻求的特定类型提示(如果它们不同),则可以直接使用 extend(一个函数)。
by
感谢指出 `extend` 可能是更好的替代品。改进 Clojure 编译器以支持我在上一个评论中链接的两个用法可能是有趣的(包括我的 OP)。

如果在未来可预见的将来不会发生这种情况,我可能需要改进 Eastwood linter 以明确告知如何改进 extend-type/extend-protocol 的用法。
by
我认为这不是编译器的问题,而是关于 `extend-type` 应支持什么语法的问题。
目前对这个问题的最终答案是什么?
我的理解是,extend-type 当前期望一个类,而不是一个 evals 到类的值。
...