为什么我在这个递归函数中得到ClassCastException

时间:2017-03-21 12:57:09

标签: recursion clojure

我写了一个递归函数来获得旅程的总费用。 costOfPath只是调用ubergraph来获取每次旅程的成本,然后这个函数添加它们并显示它。

(defn routeCost [parcel cost]
 "Calculate the total route cost"
  (if (empty? parcel)
  (print "Total Journey Cost: " cost)
     ((def first-parcel (first parcel))
    (def start (:start first-parcel))                       
     (def finish (:finish first-parcel))  
  (def value (costOfPath start finish))
   (def parcel-two (rest parcel))
   (routeCost parcel-two (+ cost value)))))

(routeCost task8 0)

任务8看起来如此:

(def task8 [(Parcel. :main-office :r131 "Plastic Wallets" "Delivery" 1)
            (Parcel. :r131 :r111 "CDs" "Delivery" 1)
            (Parcel. :r111 :r121 "USBs" "Collection" 2)
            (Parcel. :r121 :main-office "USBs" "Delivery" 2)])

该函数打印出正确的成本,但给出了classCastException。

ClassCastException practice_ubergraph.core.Parcel cannot be cast to clojure.lang.IFn  clojure.lang.Var.fn (Var.java:363)

包裹记录:

(defrecord Parcel [start            
                   finish
                   package 
                   run-type
                   weight
                   ])    

为什么会发生这种情况,如何阻止它?

编辑:我认为它与IF语句以及我将括号放在块周围的方式有关。

2 个答案:

答案 0 :(得分:2)

正如Tony所说,尝试将def s的使用限制在最高水平是个好主意。

您看到ClassCastException的原因可能就是这一行:

((def first-parcel (first parcel))

您正在定义first-parcel,然后立即使用外部括号来调用它。

将它与此示例进行比较,该示例生成类似的异常:

((def a 1))

在此示例中,a获取值1def返回var #'user/a,因此评估的表达式为:

(#'user/a)

#'user/a的值为1,然后将1视为函数。

通常,如果您看到cannot be cast to clojure.lang.IFn寻找一组双括号。

答案 1 :(得分:0)

请不要在函数中使用def。 这是一个更好的一个

(defn route-cost [parcel cost] "Calculate the total route cost" (if (empty? parcel) (print "Total Journey Cost: " cost) (let [{:keys [start finish]} (first parcel) value (cost-of-path start finish)] (route-cost (rest parcel) (+ cost value)))))

clojure的本质是你可以尽可能简洁地编写代码。通常我们在clojure中使用kebab-case来区分Java

使用let功能将修复所有内容