【问题标题】:Clojure: when to use mutable stateClojure:何时使用可变状态
【发布时间】:2011-12-07 17:47:40
【问题描述】:

我正在 Clojure 中实现 a litte "game" thing 。到目前为止,我正在函数之间传递一个“世界状态”对象。它非常“实用”,我可以通过简单地向系统输入一个虚构的世界状态来模拟游戏的任何时刻

由于 Clojure 有一个非常复杂的系统来管理状态(引用、原子...),我想知道什么是更惯用的 Clojure 编程方式,是使用它的系统还是坚持使用更实用的方法。

谢谢。

编辑:

This 是我刚刚发现的一本有趣的读物,或多或少地描述了我正在使用的模式。

【问题讨论】:

    标签: clojure


    【解决方案1】:

    纯函数已经是惯用的 Clojure。引用类型(ref、atom、agent)用于协调共享状态。

    只要没有共享任何内容(您没有在一个线程中更新世界而在另一个线程中渲染,或者在他们自己的线程上协调多个玩家)就没有理由共享状态,因此没有理由打破纯粹-功能风格。

    另一个例外是优化性能:但是当性能可以通过可变性来增强时,您希望尽可能地保持本地突变。这就是瞬态或 Java 数组的用武之地。包装这些可变优化的函数通常仍然是纯函数。

    【讨论】:

      【解决方案2】:

      Clojure 是一种函数式编程语言,旨在利用多核/SMP 处理器。在没有共享内存访问的情况下,你可以从函数式编程语言中获得很多好处,而 Erlang 确实做到了这一点,但它并没有利用所有处理器的能力。

      与“Actor 模型”语言相比,clojure 的优势在于多个线程希望以有意义且协调的方式处理相同的数据。如果您有像图像处理这样的微不足道的可并行化问题,那么您不需要这些优势,您只需将一大块数据发送给每个工作人员。当这些数据位相互依赖时,协调共享访问就成为真正的优势。

      在游戏的上下文中,您可以使用它来让多个线程更新游戏世界,并让一个线程向用户显示它。 ref 将确保用户始终看到一致的游戏世界,而许多线程都在编辑它。 如果没有这个,您将需要让每个线程负责确定何时向用户显示它,或者只有在线程上。

      除了速度之外,使用这种模型编辑游戏世界的另一个原因是允许您将执行不同操作的进程分离到不同的线程中,这是 Rich 展示的早期 clojure 示例之一一个蚂蚁模拟器,其中每只蚂蚁都有自己的线程来更新蚂蚁在棋盘上的位置,这使得代码非常简短。

      【讨论】:

        【解决方案3】:

        以当前的函数式风格编写游戏已经是正确的方式,只要只有一个线程或上下文正在写入该数据(这就是当您重复发生时发生的情况)。确实,您提到的那些设施的主要优势是在处理共享状态时。如果您想通过多线程并行化您的程序,那么利用这些工具可能会很有用。

        【讨论】:

        • 是的,程序很简单,单线程:用户输入->解析->打印一些东西->用户输入...
        • 即使你有多个线程,坚持函数式风格仍然是最好的方法——你希望尽可能地拥有纯函数,并且只在需要的地方使用 Clojure 的可变引用协调对共享游戏状态的访问(例如,具有 atom 或 ref 以便渲染线程可以看到最新的游戏世界状态)。其他一切都可以是非常纯粹/不可变的。
        猜你喜欢
        • 2012-03-11
        • 1970-01-01
        • 1970-01-01
        • 2022-01-10
        • 2011-04-28
        • 2019-06-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-10
        相关资源
        最近更新 更多