Clojure Type Hints for High Order Functions
I am creating a small application to learn Clojure and I just enabled the warnings on reflection feature for my code and I discovered a number of places where I could add type hints to enrich my code and improve performance.
However, I'm getting the warning from a few places in my code where I'm using high order functions or short anonymous syntax notation and I'm not sure how I could possibly fix those cases without expanding the function definitions.
For example, consider the following code:
(deftest test-java-expenses
(testing "Testing Expenses"
(let [total-cents (map (memfn amountInCents) expenses)]
(is (= 7406 (apply + total-cents))))))
Where expenses
is a vector containing objects of some type/class named Expense
.
It seems that the complaint is about amountInCents
, Clojure is using reflection on the arguments passed to determine their type (ie Expense
).
I can fix the warning by changing (memfn amountInCents)
for (fn [^Expense e] (.amountInCents e))
but that just makes my code harder to read and in my opinion less elegant.
I would have the same problem if I had something like this: #(.amountInCents %)
using the special syntax for anonymous function declarations.
I also considered using an annotated function to create the expense objects, one whose return type was tagged with its type, hoping the type would be inferred later, as follows
(defn new-expense ^Expense [date-string dollars cents category merchant-name]
(Expense. date-string dollars cents category merchant-name))
And then create my expenses doing:
(def expenses [(new-expense "2009-8-24" 44 95 "books" "amazon.com")
(new-expense "2009-8-25" 29 11 "gas" "shell")])
But that did not work either; the compiler still does not infer that the vector in question is a vector of Expense
objects.
Is there a way to resolve the reflection warning for cases like those above where I use the #()
, or the other case where I am passing a function as an argument to a high order function (eg memfn
)? I mean, a way without having to expand the function declaration myself (eg (fn [^Type n] ....)
Do you just need to add a type hint to the memfn
call?
From the memfn
docs (where memfn
is described as (memfn name & args)
):
name
may be type-hinted with the method receiver's type in order to avoid reflective calls.
So in your case you can use:
(memfn ^Expense amountInCents)
to avoid the reflection.
链接地址: http://www.djcxy.com/p/82576.html上一篇: clojure定义模式匹配
下一篇: 高阶函数的Clojure类型提示