Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Clojure中使用循环多次应用assoc_Clojure - Fatal编程技术网

在Clojure中使用循环多次应用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,其余保持

在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,其余保持不变。我想要的是得到一个向量,所有的值都被设置为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坐标的网格上循环,设置所有的瓷砖到同一类型的瓷砖上:因此需要一个集合方法。