在Clojure中使用循环多次应用assoc
在Clojure中是否有一种不使用recur的快速方法,可以在一行中多次将assoc应用于元素 也就是说,类似于:在Clojure中使用循环多次应用assoc,clojure,Clojure,在Clojure中是否有一种不使用recur的快速方法,可以在一行中多次将assoc应用于元素 也就是说,类似于: (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,其余保持
(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))))))
文档注释中的“终端”指的是我正在处理的一个库,它应该模拟终端,可以用于应用程序开发。您可以使用
你可以用
如果需要5个值实例的序列
32
,请使用:
如果需要将结果作为向量,请使用:
如果需要结果与现有集合的大小相同,请使用:
如果需要,可以将其打包为函数:
(defn fill [v x]
(vec (repeat (count v) x)))
(fill [3 4 2 5 8] 32)
;=> [32 32 32 32 32]
如果需要5个值实例的序列
32
,请使用:
如果需要将结果作为向量,请使用:
如果需要结果与现有集合的大小相同,请使用:
如果需要,可以将其打包为函数:
(defn fill [v x]
(vec (repeat (count v) x)))
(fill [3 4 2 5 8] 32)
;=> [32 32 32 32 32]
重新定义Clojure的核心
set
可能不是一个好主意。这里似乎也没有必要,所以我在下面的示例中直接使用了assoc
您可以不断使用
来运行所需次数的函数。它返回一个列表,因此对vec
的额外调用只是为了获得所需的数据类型:
user.core=> (let [foo [3 4 2 5 8]]
#_=> (vec (map (constantly 32) foo)))
[32 32 32 32 32]
这里是@SerCe答案的一个变体,它使用了一个reader宏,我发现这有点干净
user.core=> (let [foo [3 4 2 5 8]]
#_=> (reduce #(assoc %1 %2 32) foo (range (count foo))))
[32 32 32 32 32]
重新定义Clojure的核心
set
可能不是一个好主意。这里似乎也没有必要,所以我在下面的示例中直接使用了assoc
您可以不断使用
来运行所需次数的函数。它返回一个列表,因此对vec
的额外调用只是为了获得所需的数据类型:
user.core=> (let [foo [3 4 2 5 8]]
#_=> (vec (map (constantly 32) foo)))
[32 32 32 32 32]
这里是@SerCe答案的一个变体,它使用了一个reader宏,我发现这有点干净
user.core=> (let [foo [3 4 2 5 8]]
#_=> (reduce #(assoc %1 %2 32) foo (range (count foo))))
[32 32 32 32 32]
除了建议使用
reduce
(这些都是完全正确的),我还建议您使用一个变量进行更新(设置网格值)
假设你有这个术语定义:
(def term {:screen {:grid-width 5
:grid-height 3}
:set-char! (fn [term & other]
(println :setting other)
term)})
首先,您可以将loop/recur
替换为reduce
(用于术语更新)和(用于[x(范围2)y(范围3)][xy])列表理解的。
生成所有坐标对)
答复:
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]}
嗯。它工作,但只要你的设置字符!函数仅用于副作用(在我的例子中是打印字符串,在你的例子中是更新屏幕),你可以不减少,使用clojure为这种情况设计的函数(do[run | seq | all]
),即doseq
:
(defn fill2!
[{{:keys [grid-width grid-height]} :screen set-char! :set-char!}
tex-x tex-y color]
(doseq [x (range grid-width) y (range grid-height)]
(set-char! term x y tex-x tex-y color))
term)
这与第一个变量的作用完全相同。除了建议使用reduce
(这些都是完全正确的),我还建议您使用一个变量进行更新(设置网格值)
假设你有这个术语定义:
(def term {:screen {:grid-width 5
:grid-height 3}
:set-char! (fn [term & other]
(println :setting other)
term)})
首先,您可以将loop/recur
替换为reduce
(用于术语更新)和(用于[x(范围2)y(范围3)][xy])列表理解的。
生成所有坐标对)
答复:
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]}
嗯。它工作,但只要你的设置字符!函数仅用于副作用(在我的例子中是打印字符串,在你的例子中是更新屏幕),你可以不减少,使用clojure为这种情况设计的函数(do[run | seq | all]
),即doseq
:
(defn fill2!
[{{:keys [grid-width grid-height]} :screen set-char! :set-char!}
tex-x tex-y color]
(doseq [x (range grid-width) y (range grid-height)]
(set-char! term x y tex-x tex-y color))
term)
这与第一个变量的功能完全相同。设置功能的目的是什么?它的阴影和似乎只是一个不太有用的版本。我的代码是一个更先进的整体,在它的集合函数的名称并没有实际设置。相反,我有一个set函数(如果您愿意的话)在一个tile网格中设置一个tile(在x、y、tex-x、tex-y和color参数的帮助下),返回应用程序的当前状态。所以,我要做的是在x和y坐标设置的整个网格上循环,所有的瓷砖都是相同类型的瓷砖:因此需要一个set方法。你的set
函数的目的是什么?它的阴影和似乎只是一个不太有用的版本。我的代码是一个更先进的整体,在它的集合函数的名称并没有实际设置。相反,我有一个set函数(如果您愿意的话)在一个tile网格中设置一个tile(在x、y、tex-x、tex-y和color参数的帮助下),返回应用程序的当前状态。所以,我要做的是在整个x和y坐标的网格上循环,设置所有的瓷砖到同一类型的瓷砖上:因此需要一个集合方法。