我有一個函數,它找出圖形中用Ruby編寫的節點之間的最小距離。我將它翻譯成Clojure,但在我看來它看起來很糟糕。Clojure功能的更多的慣用和優雅的方式
數據的表示是這樣的:
hash = {:v0 [:v1 :v2 :v3]
:v1 [:v4 :v5 :v6]
:v2 [:v7 :v8 :v9]
:v3 [:v10 :v11 :v12]
:v4 [:v13 :v14 :v15]}
Ruby的功能如下:
def distance src, target, hash
return 0 if src == target
return nil if hash[src].nil?
dist = 1
if hash[src].include? target
return dist
else
arr = hash[src].map {|x| distance x, target, hash}
end
arr = arr.delete_if {|x| x.nil?}
return dist + arr.min if !arr.empty?
return nil
end
而且Clojure的功能如下:
(use 'clojure.contrib.seq-utils)
(defn distance [src target h]
(if (= src target)
0
(if (nil? (h src))
nil
(if (includes? (h src) target)
1
(let [arr (filter #(not= % nil) (map #(distance % target h) (h src)))]
(if (= (empty? arr) true)
nil
(+ 1 (apply min arr))))))))
你能向我展示一個更優雅和Clojure式的做法。那些嵌套的ifs很糟糕。
'filter'可能是懶惰的,但如果你給一個分塊以次來'map'那麼它會在評估時實現第一個塊。可能最好避免這種遞歸調用 - 如果圖中存在循環,可能會造成堆棧崩潰。 – Alex 2013-02-12 19:41:41
沒關係 - 'map'在lazy-seq裏面做了一切。所以它應該是安全的 - 只是當你把第一個元素,它實現了第一個塊。 – Alex 2013-02-12 19:52:02