在Clojure中使用C风格的封装技术?

Sta*_*ked 3 clojure

我正在研究我的第一个(非平凡的)Clojure程序我对我如何全局声明所有可变状态感到不自在.例如:

(def next-blocks (atom []))
(def num-next-blocks 1)
(def is-game-over (atom false))
(def user-name (atom (str)))
(def hs-xml (atom nil))
Run Code Online (Sandbox Code Playgroud)

由于我在工作中使用了很多C,因此我提出了使用常见的C风格封装技术的想法.它通常涉及struct对象,它作为第一个参数传递给对其进行操作的任何"成员函数".例如,见udev.

将此应用于Clojure将导致函数看起来像这样(未经测试):

(defstruct gamestate)

(defn game-new []
  (struct-map gamestate
    :level            (atom 0)
    :score            (atom 0)
    ;etc...
    ))

(def game-get-score [game]
    @(game :score))

(defn game-set-score [game new-score]
  (reset! (game :score) new-score))

(defn game-get-level [game]
  @(game :level))

(defn game-inc-level [game]
  (swap! (game :level) inc))

; etc...
Run Code Online (Sandbox Code Playgroud)

我认为这肯定是我目前正在使用的全球定义的一个步骤.

这是推荐的方式吗?或者是否有更标准的Clojure方式?

更新

我目前正在使用Clojure 1.1.0.

Ada*_*deg 6

函数式编程的基本思想是你只有很少的全局变量,但主要是局部变量(参见Rich Hickey关于状态和身份的文章).在这个范例中编写游戏可能具有挑战性,我推荐这篇关于游戏功能编程的文章(尽管这些例子在Erlang中).

我不知道你想要实现什么样的游戏.这是我对局部变量做的代码片段改进.

(defn play-game [name score blocks]
  (let [level (start-mission (:level score) blocks)]
    (if level
      (assoc score :level level)
      score)))

(defn the-whole-game []
  (let [name (ask-username)
        score (or (load-score name) {:level 0, :score 0}]
    (when-let [new-score (play-game name score [])]
       (save-score name new-score))))
Run Code Online (Sandbox Code Playgroud)

你可能想要查看clojure中的另一个俄罗斯方块克隆,但它使用的是opengl.