如何在线程( - >)宏中键入提示?

时间:2012-10-07 01:21:44

标签: clojure macros

我有一些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.

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

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

我不知道是否一直如此,但在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的parens。