>上下文
作为对自己的练习(我正在学习clojure)。我想实现Depth-first search
算法。
我是如何做到的
使用递归
(def graph
{:s {:a 3 :d 4}
:a {:s 3 :d 5 :b 4}
:b {:a 4 :e 5 :c 4}
:c {:b 4}
:d {:s 4 :a 5 :e 2}
:e {:d 2 :b 5 :f 4}
:f {:e 4 :g 1}})
(def stack [[:s]])
(def goal :g)
(defn cost [Graph start goal]
(goal (start Graph)))
(defn hasloop? [path]
(not (= (count path) (count (set path)))))
(defn atgoal? [path]
(= goal (last path)))
(defn solved? [stack]
(some true? (map atgoal? stack)))
(defn addtopath [path node]
(conj path node))
(defn pop* [stack]
(last stack))
(defn findpath [stack]
(if (not (solved? stack))
(let [first* (pop* stack) l (last first*) ]
(findpath (drop-last
(remove hasloop? (lazy-cat
(map #(addtopath first* %)
(keys (l graph))) stack)))))
[(first stack)]))
如何使用
(查找路径堆栈)
问题
我真的对如何改进这段代码非常感兴趣。在可读性、效率和性能方面。
不要使用懒猫,如果你在上面drop-last
,你的 seq 就会实现。
Clojure 中的递归应该使用 loop
/recur
来完成,以避免堆栈溢出。
不要将多个let
放在一行上:
(let [first* (pop* stack)
l (last first*)]
使用 (if-not
而不是 (if (not
。(not=
也一样
使用小写的变量名称(graph
,而不是Graph
)。保持类、记录和协议的大写。