将defrecord传递给函数clojure

时间:2017-03-20 12:22:50

标签: clojure shortest-path

我目前正在Clojure工作路线规划机器人。机器人接收一个包含其中包含一组停靠点的包裹,然后将该机器人传递到计算最短路径的函数中。

(defn journey [start end]
  (alg/pprint-path (alg/shortest-path all-edges {:start-node start, :end-node end, :cost-attr :weight})))


(defn fullpath [& stops]
  (doall (map (fn [a b] (journey a b)) stops (rest stops) )))

上述两个函数计算停靠点之间的最短路径并将其打印出来。

;;passed into robot
(defrecord Parcel [start
                   end
                   home])

;;passed into robotroute to plan journey of robot
(defrecord Robot [stops]) 

;;computes the path
(defn robotroute [robot]
  (def stops (:stops robot))
  (fullpath stops))


(def task1parcel (Parcel. :main-office :r131 :main-office))
(def task1robot (Robot. task1parcel))
(def task1 (robotroute task1robot))

(task1)

以上是我创建机器人和包裹的代码。 Robotroute是我通过机器人的功能,它意味着去除停靠点并使用完整路径规划路线。

可以定义所有功能等。但是,当尝试运行任务1时,我收到以下错误。

ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.IFn  funcprog2.core/eval13519 (form-init1291893531842170235.clj:1)

有人可以协助修复此错误吗?

同样向前发展我希望机器人能够容纳多个包裹,这样它可以连续多次交付,最好的计划是什么呢?

2 个答案:

答案 0 :(得分:1)

(defn fullpath [& stops] (doall (map (fn [a b] (journey a b)) stops (rest stops) )))

函数fullpath返回一个lazyseq。 (task1)将再次评估这个lazeseq也许你可以通过放置" task1"来获得你的结果。在repl。

例如(def list '(1 2 3))列表等于'(1 2 3). (list)将最终得到" ClassCastException clojure.lang.PersistentList无法强制转换为clojure.lang.IFn"

另一点是尝试

(defn robotroute [robot]
         (let [stops (:stops robot)] (fullpath stops)))

在clojure中有一个建议是:在定义函数时使用let而不是def来绑定变量,因为def意味着全局

答案 1 :(得分:1)

    roboroute里面的
  1. (def stops - 不应该是let吗?
  2. (robotroute task1robot)返回fullpath返回的任何内容,即(doall (map ... - 它是一个序列 - 并且序列不可调用/不是函数(如错误所示)。因此,像(task1)那样调用它会失败。