Clojure 在其自己的实例化中使用 let 变量声明?

Clojure using let variable declaration within its own instantiation?

在 Clojure 语言中,我试图将我在 let 中定义的变量作为参数传递给同一 let 中的函数。变量本身表示表示图中边的向量列表。我想传递给它的函数使用列表来确保它不会在列表中生成相同的值。

整体功能

(defn random-WS 
  ([n k] (random-WS (- n 1) k (reg-ring-lattice n k)))
  ([n k graph] 
   (cond (= n -1) graph
         :else
         (let [rem-list (for [j (range (count (graph n))) :when (< (rand) 0.5)]
                          [n (nth (seq (graph n)) j)])
               add-list (for [j (range (count rem-list))]
                          (random-WSE graph n add-list))
               new-graph (reduce add-edge (reduce rem-edge graph rem-list) add-list)]
           (random-WS (- n 1) k new-graph)))))

实际问题陈述见此处

add-list (for [j (range (count rem-list))]
    (random-WSE graph n add-list))

再次为清楚起见,函数 random-WSE 根据某些规则为我的图形生成随机边。给定当前 graph、当前节点 n 和当前要添加的边列表 add-list ,它将根据某些规则再生成一条边添加到列表中。

我唯一真正的想法是先let add-list ()先定义它,然后再重新定义它。虽然这仍然有一些相同的问题,尽管现在定义了 add-list,但在整个 for 语句中它将是 ()。因此函数 random-WSE 不会考虑列表中已有的边。

有没有办法 "evaluate" add-list 在它自己的定义中的某个定义点,以便可以在它的定义中使用它?所以我会先 "evaluate" 它到 ()for 之前,然后 "evaluate" 在 for.

的每次迭代之后

如果您有兴趣,该函数用于创建随机 Watts-Stogatz 图。

根据我从您对该算法的描述中得到的信息,添加列表在有问题的 for 循环期间增长(累积)。积累(对于积累的广泛接受)是一个强烈的信号,你应该使用 reduce

(reduce (fn [add-list j] (conj add-list (random-WSE graph n add-list))) [] (range (count rem-list))

基本上你是在 let 中链接结果,因为第一次计算的结果(导致 rem-list)是第二次计算的唯一输入(你的问题点) 这又是您第三次计算的唯一输入,这最终是您最终计算步骤(您的递归步骤)的唯一输入。如果这个链接听起来很熟悉,那是因为它是:考虑根据线程宏 ->.

重新制定您的 let 构造

即类似于

的内容
(defn- rem-list [graph n]
   ...)
(defn- add-list [remlist n]
   ...)
(defn- new-graph [addlist]
   ...)

(defn random-ws 
   ([n k] ...)
   ([graph n k] ;; <- note the moved parameter
     (cond (= n -1) graph
           :else    
           (-> graph
               (rem-list n)
               (add-list n)
               (new-graph)
               (random-ws (dec n) k))))

然后您可以将 add-list 表示为简单的递归函数(可能引入累加器变量)或使用 cgrand 解释的 reduce 变体。