有没有办法在 clojure 线程宏中包含类型提示?

Is there a way to include type hints inside the clojure threading macro?

例如,如上例here

=> (-> "a b c " .toUpperCase (.replace "A" "X") (.split " ") first)
=> "X"

我希望能够做类似

的事情
 => (-> ^String "a b c " .... etc etc 

避免反射惩罚,尤其是。在与 java 代码交互时。

好吧,至少在你的情况下,没有反射惩罚。

 user=> (set! *warn-on-reflection* true)
 true
 user=> (-> "a b c " .toUpperCase (.replace "A" "X") (.split " ") first)
 "X"

如果您想更加确定:

 user=> (def i 23)
 #'user/i
 user=> (.toString i)
 Reflection warning, NO_SOURCE_PATH:1:1 - reference to field toString can't be resolved.
 "23"

是的,有可能。

如果您需要对 -> 的初始参数进行类型提示,您可以直接在 -> 形式的内部或外部进行:

(-> ^String (foo) .toUpperCase)

(let [^String f (foo)]
  (-> f .toUpperCase))

两种情况都不会反射。

如果您希望类型提示的值出现在 -> 链的中间步骤,那么您可以通过在 -> 步骤上放置类型提示来对其进行类型提示:

;; note the type hints on identity and (identity)

(-> ^String (foo) .toUpperCase ^String identity .toLowerCase)

(-> ^String (foo) .toUpperCase ^String (identity). toLowerCase)

同样,两种情况都不会反射。

(在 1.7.0-alpha5 REPL 中测试。)

可以使用 -> 宏键入提示表达式。而以下使用反射:

(set! *warn-on-reflection* true)
(def s "1")
(-> s .toString)
;; Reflection warning, NO_SOURCE_PATH:1:1 - reference to field toString can't be resolved.
;;= "1"

这不是:

(-> ^String s .toString)
;;= "1"

也许如果您分享一个您发现很难或无法键入提示的特定表达式,我们可以更好地帮助您。

有一种已知情况,即附加到宏 &form 表达式的类型提示被丢弃,请参阅此 JIRA 票证 Macroexpansion discards &form metadata。也许这就是您所看到的?