Язык, поддерживающий сериализацию сопрограмм - PullRequest
7 голосов
/ 09 апреля 2009

Я не думаю, что такая поддержка существует в современных языках. Я думаю, что то, что я хочу сделать, может быть решено с помощью «механизма рабочего процесса». Но проблема с рабочими процессами, как правило, такова:

  1. Декларативный / многословный, и я считаю императивный стиль гораздо более лаконичным
  2. Тяжеловес, у меня будет много простых, но разнообразных конечных автоматов

Я исследовал сериализацию итераторов в C # , но это не дает мне того, где я хочу быть. В настоящее время я смотрю на то, как собрать DSL в Boo , но не уверен, смогу ли я получить поведение, подобное сопрограммному, в 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. Он добавляет поддержку итератора / yield в 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 #, я почти уверен, что могу вернуться к "технике" / (хак) , которую я использовал для сериализации итераторов.

Ответы [ 5 ]

8 голосов
/ 09 апреля 2009

Забавно, что вы должны спросить об этом сегодня, а потом я прочитал о Продолжении в моно . Похоже, что вы ищете. В частности, есть ссылка на Microthreading в Second Life , включая это описание:

SecondLife требуется, чтобы код был приостановлено в любой момент времени и чтобы все его состояние было сериализуемым в формат, подходящий для хранения в базу данных. Сериализованное состояние может быть восстановлен в другом момент времени или другой компьютер (например, во время движения от узла к узлу).

Если я вас не правильно понял, это может быть хороший путь для изучения.

5 голосов
/ 01 марта 2010

Я нашел лучшую поддержку для сериализации сопрограмм , кажется, в Lua через библиотеку Плутон .

Я играю Mono 2.6 , но не смог заставить работать сопрограммы. Затем я некоторое время экспериментировал с Python / IronPython, но поддержка сериализации отсутствовала.

Теперь с Lua мне придется взаимодействовать через P / Invoke из .NET в Lua , что является трудной задачей для работы как на Linux, так и на Windows, но в конечном итоге, если я ищу язык сценариев для поддержки игры, вероятно, лучше всего использовать то, что уже популярно выбирается.

Обновление

В итоге я отказался от Луа. Я слишком увяз в вопросах интеграции. Я вернулся на Python. Я использую выражения выхода Python для своих сопрограмм, и работаю над тем, что pickle не поддерживает генераторы .

В моем случае состояние программы не всегда имеет активные сопрограммы, что означает, что иногда я могу выбрать состояние. В противном случае я сохраняю последнее состояние рассола и «историю повторов» действий с тех пор. Затем восстановление состояния - это просто открепление последнего состояния и повтор любых действий.

1 голос
/ 09 апреля 2009

Вы ищете продолжения ?

На любом языке, который поддерживает замыкания, можно писать программы в стиле продолжения продолжения и реализовывать вызов / cc вручную.

call/cc является call-with-current-continuation.

1 голос
/ 09 апреля 2009

Возможно, вы захотите взглянуть на рабочий процесс Windows:

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

Он предназначен для использования таким образом, с возможностью сохранять рабочий процесс, если на нем отсутствует активность, а также с возможностью перезапуска.

Хотя технически это не поддержка языков, это должно быть сделано.

0 голосов
/ 04 сентября 2011

Последняя версия Java включает в себя Rhino, интерпретатор javascript с поддержкой сериализуемых продолжений. Есть также Плутон + Луа, который я сейчас изучаю.

Мне бы хотелось услышать о том, какой путь вы выбрали, поскольку сериализуемые продолжения важны для проекта http://weaverengine.com.

...