7

我认为当前语言中不存在这种支持。我认为我想做的事情可以通过“工作流引擎”来解决。但是我对工作流程的问题通常是:

  1. 声明式/冗长,我发现命令式风格更简洁
  2. 重量级,我会有很多简单但多样的小状态机

我已经研究了 C# 中的序列化迭代器,但这并没有让我得到我想要的确切位置。我目前正在考虑在Boo中组合一个 DSL,但不确定我是否能够在 Boo 中获得类似协程的行为,并且也能够对其进行序列化。

例子

这是我想做的有限的虚构示例。主要问题是,在例程中的任何时候,您都可能需要获取用户输入。输入之间的时间可能很长,因此需要将服务状态序列化到磁盘。

    def RunMachine(user)
      var lever = user.ChooseLever()
      lever.Pull()
      var device = CreateDevice(user)
      machine.Add(device)
      machine.Run()

   def CreateDevice(user)
      var color = user.ChooseColor()
      var shape = user.ChooseShape()
      return Device(color, shape)

更新

我在 CPython 中有一个工作的“引擎”。它搭载了 python 中的迭代器/产量支持。所以代码看起来像这样:

def escape(self, you):        
    roll = yield self.game.rollDice(you)
    if roll < 5:
        self.caughtAction(you)                  

哪里rollDice可以打断。通过一些用户操作。然而, CPython不会序列化迭代器。

由于游戏的整个状态可以定义为一系列命令,因此我将游戏状态序列化到协程开始的位置,然后是剩余的命令列表。所以保存/恢复看起来像这样:

def dumpGameState(game):
    if gameState.partialState:
        return pickle.dumps({ 'partialState': game.partialState, 'partialInputs': game.partialInputs })

    return pickle.dumps(game)

def loadGameState(data):
    state = pickle.loads(data)

    if state.__class__ is Game:
        return state

    r = pickle.loads(state['partialState'])

    for input in state['partialInputs']:
        game.execute(**input)   
    return game

目前的调查

我仍然觉得这不令人满意。因为我最终不得不在几乎每种方法上都使用“yield”。我宁愿不必专门装饰一个方法。它在序列化方面也很失败。

目前我正在研究走函数式路线,因为函数式语言似乎对元编程/DSL 创建有更好的支持。目前在看

我希望通过足够强大的元编程设施,我可以自动化状态存储机制。另外,如果我走 F# 路线,我很确定我可以依靠我用来序列化迭代器的“技术”/(hack) 。

4

5 回答 5

7

有趣的是你今天应该问这个,然后我读到了Mono 中的 Continuations。看起来像你所追求的那种东西。特别是在 Second Life 中有对 Microthreading的引用,包括以下描述:

SecondLife 要求代码在任何时间点暂停,并且其整个状态可以序列化为适合存储到数据库中的格式。然后可以在不同的时间点或在不同的计算机上恢复序列化状态(例如,在从一个节点移动到另一个节点时)。

除非我误解了你,否则这可能是一个很好的探索途径。

于 2009-04-09T18:25:44.833 回答
4

我发现对序列化协程的最佳支持似乎是通过Pluto库在 Lua 中。

我试用Mono 2.6,但无法让协程工作。然后我用 Python/IronPython 试验了一段时间,但缺乏序列化支持。

现在使用 Lua,我必须通过 P/Invoke 从 .NET 连接到 Lua,这被证明是在 Linux 和 Windows 上工作的挑战,但最终如果我正在寻找一种脚本语言来支持游戏,可能最好使用已经普遍选择的东西。

更新

我最终暂时放弃了 Lua。我在集成问题上陷入了困境。我又回到了 Python。我正在为我的协程使用python yield 表达式,并解决pickle 不支持 generators的问题。

就我而言,程序状态并不总是有活动的协程,这意味着有时我可以腌制状态。否则,我会存储最后一个泡菜状态,以及此后操作的“重播历史”。然后恢复状态只是取消最后一个状态,并重放任何动作。

于 2010-03-01T19:15:00.240 回答
1

您在寻找作吗?

在任何支持闭包的语言中,都可以以连续传递风格编写程序并手动实现 call/cc。

call/cccall-with-current-continuation.

于 2009-04-09T15:38:15.207 回答
1

您可能想看看 Windows 工作流:

http://msdn.microsoft.com/en-us/netframework/aa663328.aspx

它旨在以这样的方式使用,如果工作流处于不活动状态,则能够保持工作流,以及重新启动它的能力。

虽然从技术上讲它不是语言支持,但它应该可以完成工作。

于 2009-04-09T15:10:37.497 回答
0

最新版本的 Java 包括 Rhino,一个支持可序列化延续的 javascript 解释器。还有 Pluto+Lua,我现在正在研究。

我想听听您最终选择的路径,因为可序列化的延续对http://weaverengine.com项目很重要。

于 2011-09-04T12:51:07.583 回答