Правильное использование изменяемых / неизменяемых списков - PullRequest
16 голосов
/ 29 августа 2010

В данный момент я пытаюсь понять функциональное программирование в Scala, и я столкнулся с проблемой, которую не могу понять сам.

Представьте себе следующую ситуацию:

У вас есть два класса: Контроллер и Бот . A Bot - это независимый субъект, который инициируется контроллером 1012 *, выполняет дорогостоящую операцию и возвращает результат в Controller . Поэтому цель Controller легко описать: создать несколько объектов Bot , запустить их и получить результат.

Пока все хорошо; Я могу реализовать все это без использования изменяемых объектов.

Но что мне делать, если мне нужно сохранить результат, который возвращает Bot , чтобы использовать его позже как вход для другого Bot (и позже означает, что Я не знаю, когда во время компиляции!)?

Сделать это с изменяемым списком или коллекцией довольно легко, но я добавляю много проблем в свой код (поскольку мы имеем дело с параллелизмом здесь)

Можно ли, следуя парадигме FP, решить эту проблему, используя безопасные неизменяемые объекты (списки ...)?

Кстати, я новичок в FP, поэтому этот вопрос может показаться глупым, но я не могу понять, как это решить :)

Ответы [ 2 ]

7 голосов
/ 29 августа 2010

Актеры обычно имеют внутреннее состояние, будучи самими изменчивыми животными. Обратите внимание, что актеры не являются предметом FP.

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

case Msg(info) =>
  val v1 = new Bot !! Fn1(info)
  val v2 = new Bot !! Fn2(info)
  val v3 = new Bot !! Fn3(info)
  val v4 = new Bot !! Fn4(v1(), v2(), v3())
  reply(v4())

В этом случае - потому что !! возвращает значения Future - v1, v2 и v3 будут вычисляться параллельно. Сообщение Fn4 получает в качестве параметров примененное фьючерсы, то есть оно будет ожидать, пока все значения не будут вычислены, прежде чем оно начнет вычисляться.

Аналогичным образом, ответ будет отправлен только после того, как v4 будет вычислено, так как будущее также применяется.

Действительно функциональным способом решения этих задач является функциональное реактивное программирование , или сокращенно FRP. Это другая модель, чем актеры.

Красота Scala, однако, в том, что вы можете комбинировать такие парадигмы настолько, чтобы лучше соответствовать вашей проблеме.

6 голосов
/ 30 августа 2010

Вот как Эрланг-подобный актер может выглядеть в Scala:

case class Actor[State](val s: State)(body: State => Option[State]) { // immutable
  @tailrec
  def loop(s1: State) {
    body(s1) match {
      case Some(s2) => loop(s2)
      case None => ()
    }
  }

  def act = loop(s)
}

def Bot(controller: Actor) = Actor(controller) { 
  s => 
    val res = // do the calculations
    controller ! (this, res)
    None // finish work
} 

val Controller = Actor(Map[Bot, ResultType]()) {s =>
  // start bots, perhaps using results already stored in s
  if ( 
    // time to stop, e.g. all bots already finished 
  )
    None
  else
    receive {
      case (bot, res) => Some(s + (bot -> res)) // a bot has reported result
    }
}

Controller.act
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...