我正在创建一个小应用程序来学习Clojure,我刚刚为我的代码启用了反射功能警告,我发现了一些可以添加类型提示的地方,以丰富我的代码并提高性能。
但是,我从我的代码中的几个地方收到警告,其中我使用高阶函数或简短的匿名语法表示法,我不确定如何修复这些案例不扩展功能定义。
例如,请考虑以下代码:
(deftest test-java-expenses
(testing "Testing Expenses"
(let [total-cents (map (memfn amountInCents) expenses)]
(is (= 7406 (apply + total-cents))))))
其中expenses
是包含某个名为Expense
的类型/类的对象的向量。
似乎投诉是关于amountInCents
,Clojure正在对传递的参数进行反思以确定其类型(即Expense
)。
我可以通过更改(memfn amountInCents)
(fn [^Expense e] (.amountInCents e))
来修复警告,但这会让我的代码更难阅读,而且我认为不那么优雅。
如果我有这样的东西,我会遇到同样的问题:#(.amountInCents %)
使用匿名函数声明的特殊语法。
我还考虑使用带注释的函数来创建费用对象,其返回类型用其类型标记,希望稍后推断出类型,如下所示
(defn new-expense ^Expense [date-string dollars cents category merchant-name]
(Expense. date-string dollars cents category merchant-name))
然后创建我的费用:
(def expenses [(new-expense "2009-8-24" 44 95 "books" "amazon.com")
(new-expense "2009-8-25" 29 11 "gas" "shell")])
但这也不起作用;编译器仍然没有推断出有问题的向量是Expense
个对象的向量。
有没有办法解决上面我使用#()
的情况下的反射警告,或者我将函数作为参数传递给高阶函数的另一种情况(例如{{1 }})?我的意思是,一种不必自己扩展函数声明的方法(例如memfn
答案 0 :(得分:2)
您是否只需要在memfn
电话中添加类型提示?
来自memfn
docs(其中memfn
被描述为(memfn name & args)
):
name
可以使用方法接收器进行类型提示 键入以避免反射调用。
因此,在您的情况下,您可以使用:
(memfn ^Expense amountInCents)
避免反思。