嵌套测试的功能版本是什么?

时间:2018-09-27 23:00:52

标签: clojure functional-programming

我正在将一些C ++代码转换为Clojure,我想要 返回图%C2%A0,其中添加了许多边。 我输入了顶点数,图形和 测试谓词(例如,可能依赖于i,j,随机性等的函数)是这样的:

g

当然,问题在于(defn addSomeEdges [v g test-p] (doseq [i (range v)] (doseq [j (range (dec i))] (if test-p (add-edges g [i j] ) ))) g) 返回新的(add-edges)。请问如何使用最佳实践Clojure捕获此更新的图形?在C ++中看起来是如此简单自然。

2 个答案:

答案 0 :(得分:3)

将信息分成两部分,以迭代方式积累信息就好像是一种归约函数:

  • 生成一堆要考虑的边缘。
  • 测试每条边,如果通过则将其包括在内。否则将结果按原样传递

可以使用reduce

来写
user> (defn add-edge [g i j]
        (assoc g i j))
#'user/add-edge

user> (add-edge {1 2} 2 1)
{1 2, 2 1}

user> (defn addSomeEdges [v g test-p]
        (reduce (fn [graph [i j]]        ;; this takes the current graph, the points,
                  (if (test-p graph i j) ;; decides if the edge should be created.
                    (add-edge graph i j) ;; and returns the next graph
                    graph))              ;; or returns the graph unchanged.
                g  ;; This is the initial graph
                (for [i (range v)    
                      j (range (dec i))]
                  [i j])))  ;; this generates the candidate edges to check.
#'user/addSomeEdges

让我们运行它!

user> (addSomeEdges 4 {1 2} (fn [g i j] (rand-nth [true false])))
{1 2, 2 0}
user> (addSomeEdges 4 {1 2} (fn [g i j] (rand-nth [true false])))
{1 2, 3 0}
user> (addSomeEdges 4 {1 2} (fn [g i j] (rand-nth [true false])))
{1 2, 2 0, 3 1} 

当您想到其他测试时,可以将这些调用组合在一起:

user> (as-> {1 2} g
        (addSomeEdges 4 g (fn [g i j] (rand-nth [true false])))
        (addSomeEdges 7 g (fn [g i j] (< i j)))
        (addSomeEdges 9 g (fn [g i j] (contains? (set (keys g)) j))))
{1 2, 3 1, 4 1, 5 3, 6 4, 7 5, 8 6}

答案 1 :(得分:0)

对此有多种解决方案。但是,有时候,当您遇到根本上可变/必须的问题时,应该只使用可变/必要的解决方案:

; simplest version using mutation
(defn addSomeEdges [v g test-p]
  (let [g-local (atom g)]
    (doseq [i (range v)]
      (doseq [j (range (dec i))]
        (when (test-p i j ...)  ; what other args does this need?
          (swap! g-local add-edges [i j]))))
    @g-local))

我对test-p的对称性不太确定,因此该部分可能需要改进。

请注意,swap!会这样呼叫add-edges

(add-edges <curr val of g-local> [i j])

有关更多信息,请参见the Clojure CheatSheetClojureDocs.org