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
变体。
在 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
变体。