Reputation: 57333
For example, as in the example here,
=> (-> "a b c " .toUpperCase (.replace "A" "X") (.split " ") first)
=> "X"
I'd like to be able to do something like
=> (-> ^String "a b c " .... etc etc
to avoid the reflection penalties, esp. in interfacing with java code.
Upvotes: 3
Views: 425
Reputation: 9930
It is possible to type hint expressions using the ->
macro. While the following uses reflection:
(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"
This doesn't:
(-> ^String s .toString)
;;= "1"
Maybe if you share a specific expression where you are finding it hard or impossible to type hint we can help you better.
There is a known situation where the type hint attached to the macro's &form
expression is discarded, see this JIRA ticket Macroexpansion discards &form metadata. Maybe this is what you are seeing?
Upvotes: 4
Reputation: 84369
Yes, it is possible.
If you need to type-hint the initial argument to ->
, you can do it directly, either inside or outside the ->
form:
(-> ^String (foo) .toUpperCase)
(let [^String f (foo)]
(-> f .toUpperCase))
There will be no reflection in either case.
If the value that you wish to type-hint arises at an intermediate step in the ->
chain, then you can type-hint it by putting the type hint on the ->
step:
;; note the type hints on identity and (identity)
(-> ^String (foo) .toUpperCase ^String identity .toLowerCase)
(-> ^String (foo) .toUpperCase ^String (identity). toLowerCase)
Again, there will be no reflection in either case.
(Tested at a 1.7.0-alpha5 REPL.)
Upvotes: 2
Reputation: 20245
Well, in your case at least, there are no reflection penalties.
user=> (set! *warn-on-reflection* true)
true
user=> (-> "a b c " .toUpperCase (.replace "A" "X") (.split " ") first)
"X"
If you want to be even more sure:
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"
Upvotes: 1