【问题标题】:How can you type hint within the threading (->) macro?如何在线程 (->) 宏中键入提示?
【发布时间】:2023-03-31 09:36:01
【问题描述】:

我有一些 Clojure 代码试图通过几层 Java 代码进行互操作(在本例中,java.nio.Path 通过java.nio.file.WatchEvent<?>

(defn unroll-event
  [^WatchEvent event]
  { :kind (.kind event)
    :context (.context event)
    :path (-> event .context .toAbsolutePath .toString)})

在这段代码中,我输入了提示 event,所以我认为它应该能够弄清楚 .context 应该返回什么,因此,能够弄清楚看看.toAbsolutePath.toString 做了什么。我认为在这种情况下,由于.context 的定义返回了泛型类型T,我想知道是否可以键入提示对.context 的调用。我尝试将^java.nio.file.Path 分别添加到.context^Path^String.toAbsolutePathtoString,但我仍然收到警告:

Reflection warning, junkcode/core.clj:28 - reference to field toAbsolutePath can't be resolved.
Reflection warning, junkcode/core.clj:28 - reference to field toString can't be resolved.

在这种情况下我可以做些什么吗?是因为-> 是一个宏,并且其中有特殊的类型提示规则吗?

【问题讨论】:

  • 它扩展到什么?使用clojure.walk/macroexpand-all

标签: clojure macros


【解决方案1】:

(-> x .blah ^String .bar) 基本上扩展为(^String .bar (.blah x)),这显然不是您想要的提示。关键是类型提示在任何上下文(例如宏)中都没有特殊行为:它只是应用于源代码符号的元数据。在您的示例-> 中,没有任何地方可以将元数据放在输入表单上,这会导致它在输出表单中出现在您想要的位置。所以你需要写一些其他的形式,比如(-> ^Path (.context event) .toAbsolutePath str)

此外,Clojure 的推理器对泛型类型一无所知,因此方法返回 T 被视为方法返回对象,这解释了为什么您需要在这里提示。

【讨论】:

    【解决方案2】:

    我不知道是否一直都是这样,但在 Clojure 1.4.0、1.5.1 和 1.6.0 中,只要使用括号,您就可以在 -> 中的任何位置输入提示:

    user=> (set! *warn-on-reflection* true)
    true
    user=> (fn [^java.nio.file.WatchEvent e] 
             (-> e ^java.nio.file.Path .context .toAbsolutePath))
    Reflection warning, /private/var/folders/9_/wdph6m796zzc8trzcbtcmhrn5bjpt0/T/form-init8364673644863044068.clj:1:35 - reference to field toAbsolutePath on java.lang.Object can't be resolved.
    #<user$eval1995$fn__1996 user$eval1995$fn__1996@8128f39>
    user=> ; but no warning if we do
    user=> (fn [^java.nio.file.WatchEvent e]
             (-> e ^java.nio.file.Path (.context) .toAbsolutePath))
    #<user$eval1999$fn__2000 user$eval1999$fn__2000@4747e32a>
    

    唯一的区别是 .context 周围的括号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-15
      • 2011-04-12
      • 2021-04-28
      • 2017-03-28
      • 2019-04-24
      • 2022-01-13
      • 2017-06-29
      • 2023-04-03
      相关资源
      最近更新 更多