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

时间:2015-01-28 16:41:07

标签: clojure

例如,如示例here中所述,

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

我希望能够做类似

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

避免反射惩罚,尤其是在与java代码的接口。

3 个答案:

答案 0 :(得分:4)

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

(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。也许这就是你所看到的?

答案 1 :(得分:2)

是的,这是可能的。

如果您需要键入提示->的初始参数,您可以直接在->表单内部或外部执行此操作:

(-> ^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。)

答案 2 :(得分:1)

嗯,至少在你的情况下,没有反映惩罚。

 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"