我有一个游戏状态表示为地图和一些逻辑,可以在每个游戏中更新该状态' tic'。但我无法弄清楚如何以任何理智的方式构建更新功能。
这样构造函数的惯用模式是什么?
以下是我想要做的一些伪代码:
(defn tic [g] "Return an updated game"
g1 = (update-in g [:day] inc)
g2 = (if (some-cond) (some-update-func g1) g1)
g3 = (update-in g2 [:fu] fu-update)
... many more ...
g-last)
我不太关心中间状态,但使用 - >宏不起作用(因为有一些条件)。
有效的黑客正在使用重置的本地原子!对于每一行'在更新功能中。但这不可能是它应该如何完成的?!
答案 0 :(得分:6)
我建议在一个名称很好的函数中提取每个步骤,这样就可以使用 - >。伪代码:
(defn tic [g]
(-> g
inc-day
random-weather
grow-trees
...))
对于任何条件逻辑,您可以执行类似于g2步骤中的操作。
也许你会发现synthread lib有用。我发现this video很有启发性。
同时查看cond->,看看你如何混合 - >与一些cond。例如,您的cond可能如下所示:
(cond-> g
true (update-in [:day] inc)
(some-cond) some-update-fund
true (update-in [:fu] fu-update))
答案 1 :(得分:3)
如果对于条件步骤,您仍然可以使用->
,将操作包装在匿名函数中。
(-> g0
...
(#(if (some-cond) (u %) %))
...)
如果你担心效率(你提到这是游戏),我建议你使用cond->
或者创建自己的宏。 cond->
要求对始终为线程的表达式重复true
,这可能很乏味,具体取决于线程中的项目数。
这是一个可以与->
结合使用的宏,可以避免过度创建匿名函数并避免cond->
的重复性:
(defmacro maybe [val sym cond expr]
`(let [~sym ~val] (if ~cond ~expr ~sym)))
可以像这样使用:
(-> g0
...
(maybe gn (some-cond gn) (updater gn))
...)
如果您不需要在条件表达式中使用部分处理的值gn
,则可以使用cond->
代替maybe
:
(-> g0
...
(cond-> (some-cond g0) updater)
...)
另一个例子:
(-> 10 (maybe gn (= gn 10) (* gn 100)))
评估为1000