2014-07-14 23 views
3

我有一个表示为地图的游戏状态和一些更新每个游戏'tic'状态的逻辑。但我无法弄清楚如何以任何理智的方式构建更新功能。如何在Clojure中构造复杂的“状态更新函数”?

构建这样的函数的习惯模式是什么?

这里是我想要做的一些伪代码:

(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) 

我真的不关心中间状态,但使用 - >宏不工作(因为有一些条件语句)。

工作的黑客正在使用重置的本地原子!对于更新函数中的每个'行'。但这不可能是它应该如何完成的!

回答

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)) 
+0

的命名函数的组合,逻辑块,并且synthread LIB看起来像一个很好的解决方案。它有类似于其他答案中描述的'mabey'宏的宏(还有更多)。 – 4ZM

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

+0

你应该看看'cond->',我相信它会很好地代替'maybe'。 – omiel

+0

@omiel'cond->'绝对是一种选择,所以我相应地编辑了我的答案。但是,如果大多数情况是“真实的”,它看起来很讨厌,如果你想使用条件中的当前值,它就不起作用。 我编辑了我的答案,以使'maybe'宏实际上有用 - 它只是移动匿名函数而不是解决它。 – matvore

+1

您误解了:我建议您在' - >'内嵌套'cond->'形式,而不是仅仅使用'cond->'。 – omiel

相关问题