我想执行特定操作的给定时间量(例如,生成部落)。每次我想使用前一次迭代的输出作为下一次迭代的输入。
我通过对n个元素的集合进行虚拟减少来实现它,然后我只考虑累加器并从集合中丢弃元素。
(defn generate-game [world n-tribes]
(let [ game (create-game world)
game (reduce (fn [acc, _] (:game (generate-tribe acc))) game (repeat n-tribes :just_something))]
game))
我认为有更好的方法可以做到这一点。你能帮我找到吗?
答案 0 :(得分:4)
如果相同的功能重复n-tribes
次,那么使用iterate并获取n-tribes
'元素应该有效:
(defn generate-game [world n-tribes]
(let [ game (create-game world)
game (nth (iterate generate-tribe game) n-tribes)]
game))
请记住,iterate
会创建一个懒惰的序列,因此在您请求之前不会计算任何内容。
另一种选择是将comp应用于函数列表,毕竟它是一个简单的函数组合:
(generate-tribe (generate-tribe .... (generate-tribe game) ....))
n-tribes times
类似于:
(defn generate-game [world n-tribes]
(let [ game (create-game world)
game ((apply comp (repeat n-tribes generate-tribe)) game)]
game))
完全表达了这个想法。
答案 1 :(得分:2)
不是Clojure专家,但我希望
(defn generate-game [world n-tribes]
(nth (iterate generate-tribe (create-game world)) n-tribes))
或(更简洁)
(defn generate-game [world n-tribes]
(let [game (create-game world)]
(nth (iterate generate-tribe game) n-tribes)))
工作
答案 2 :(得分:1)
问题中使用的方法很好,但使用范围
(defn generate-game [world n-tribes]
(reduce (fn [acc _] (:game (generate-tribe acc)))
(create-game world)
(range n-tribes)))
由于范围对象知道如何智能地减少自己,因此这将变成一个循环。这是范围的reduce
方法:
public Object reduce(IFn f, Object start) {
Object ret = f.invoke(start,n);
for(int x = n+1;x < end;x++)
ret = f.invoke(ret, x);
return ret;
}
如果您的游戏状态最终会在原子中结束,那么您也可以考虑dotimes
来更新它。
(defn generate-game [world n-tribes]
(let [game (atom (create-game world))]
(dotimes [_ n-tribes] (swap! game (comp :game generate-tribe)))
game))
迭代也是一个很好的解决方案。在Iteratively apply function to its result without generating a seq进行了更多讨论。