高阶函数的Clojure类型提示

时间:2015-12-19 14:46:23

标签: clojure

我正在创建一个小应用程序来学习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

1 个答案:

答案 0 :(得分:2)

您是否只需要在memfn电话中添加类型提示?

来自memfn docs(其中memfn被描述为(memfn name & args)):

  

name可以使用方法接收器进行类型提示   键入以避免反射调用。

因此,在您的情况下,您可以使用:

(memfn ^Expense amountInCents)

避免反思。