Clojure中有没有使用recur的快速方法,可以连续多次将一个关联应用于一个元素?
就是这样:
(defn set-thing
[foo i val]
(assoc foo i val))
(let [foo [3 4 2 5 8]]
(last (for [i (range 0 (count test))]
(set-thing foo i 32)))
上面的代码显然没有做我想要做的事情。上面的函数只返回一个向量,其中最后一个值为32,其余值保持不变。我所追求的是获得一个向量,其中所有值都设置为32。
使用set函数是绝对必要的,因为我的代码看起来与上面代码的代码明显不同:因此阻止了map的使用。实际代码在结构上的结构中非常深。
是否有可能再次实现这种效果,而不使用复发?
修改
这是一段使用循环和重复的代码,做我想要实现的目标。
(defn fill!
"Fills the terminal with one specific tile."
[{:keys [screen] :as term} tex-x tex-y color]
(let [grid-width (screen :grid-width)
grid-height (screen :grid-height)]
(loop [x 0
y 0
term term]
(if (= x grid-width)
(if (= y grid-height)
term
(recur 0 (inc y) ((term :set-char!) term x y tex-x tex-y color)))
(recur (inc x) y ((term :set-char!) term x y tex-x tex-y color))))))
"终端"在doc评论中指的是我正在研究的应该模拟终端的库,可以用于应用程序开发。
答案 0 :(得分:3)
您可以使用reduce
(let [foo [3 4 2 5 8]]
(reduce (fn [acc k]
(set acc k 32))
foo
(range (count foo))))
答案 1 :(得分:1)
如果您需要值为<asp:ListView ID="ListView1" DataSourceID="SqlDataSource1" runat="server" />
的5个实例的序列,请使用repeat
:
32
如果您需要将结果作为矢量,请使用vec
:
(repeat 5 32)
;=> (32 32 32 32 32)
如果您需要将结果与现有集合的大小相同,请使用count
:
(vec (repeat 5 32))
;=> [32 32 32 32 32]
如果您愿意,可以将其打包成一个函数:
(vec (repeat (count [3 4 2 5 8]) 32))
;=> [32 32 32 32 32]
答案 2 :(得分:1)
除了使用reduce
的建议(完全正确的建议)之外,我还建议您更新一个变体(设置网格值)
假设您有这个术语定义:
(def term {:screen {:grid-width 5
:grid-height 3}
:set-char! (fn [term & other]
(println :setting other)
term)})
首先,您可以使用loop/recur
(用于术语更新)和reduce
列表推导(for
生成所有坐标对)的组合替换(for [x (range 2) y (range-3)] [x y])
< / p>
(defn fill!
[{{:keys [grid-width grid-height]} :screen
set-char! :set-char!}
tex-x tex-y color]
(reduce (fn [term [x y]] (set-char! term x y tex-x tex-y color))
term
(for [x (range grid-width)
y (range grid-height)]
[x y])))
在repl中:
user> (fill! term 101 102 103)
:setting (0 0 101 102 103)
:setting (0 1 101 102 103)
:setting (0 2 101 102 103)
:setting (1 0 101 102 103)
:setting (1 1 101 102 103)
:setting (1 2 101 102 103)
:setting (2 0 101 102 103)
:setting (2 1 101 102 103)
:setting (2 2 101 102 103)
:setting (3 0 101 102 103)
:setting (3 1 101 102 103)
:setting (3 2 101 102 103)
:setting (4 0 101 102 103)
:setting (4 1 101 102 103)
:setting (4 2 101 102 103)
{:screen {:grid-width 5, :grid-height 3}, :set-char! #function[user/fn--19918]}
确定。它有效,但只要你的set-char!函数仅用于副作用(在我的情况下打印字符串,在你的更新屏幕中),你可以没有减少,使用为这个确切的情况设计的clojure函数(do[run|seq|all]
),即{ {1}}:
doseq
与第一个变体完全相同。
答案 3 :(得分:0)
重新定义Clojure的核心set
可能不是一个好主意。这里似乎也没有必要,所以我在下面的例子中直接使用了assoc
。
您可以使用constantly
运行所需的次数。它会返回一个列表,因此对vec
的额外调用只是为了获得所需的数据类型:
user.core=> (let [foo [3 4 2 5 8]]
#_=> (vec (map (constantly 32) foo)))
[32 32 32 32 32]
这是@ SerCe使用读取器宏的答案的变体,我觉得它更清洁。
user.core=> (let [foo [3 4 2 5 8]]
#_=> (reduce #(assoc %1 %2 32) foo (range (count foo))))
[32 32 32 32 32]