I've constructed a small example to help clarify the problem:
case class Player(target: Option[Target])
case class Target(x: Int, y: Int) {
def moveRight = copy(x = x + 1)
}
case class Game(players: List[Player], targets: List[Target])
object GameLogic extends App {
val target0 = new Target(0, 0)
val target1 = new Target(1, 2)
val target2 = new Target(0, 0)
val player0 = new Player(None)
val player1 = new Player(Some(target2))
val game = new Game(player0 :: player1 :: Nil,
target0 :: target1 :: target2 :: Nil)
val updatedGame = game.copy(targets = game.targets.map(_.moveRight))
println(updatedGame)
}
//prints Game(List(Player(None), Player(Some(Target(0,0)))),List(Target(1,0), Target(2,2), Target(1,0)))
The problem is that player1's copy of target didn't get updated in the game update step. I read through the Lens paper referenced earlier in this thread, but wasn't sure how a lens was supposed to update an instance that appears in multiple locations in an object tree. Or is there a better way to organize this data to avoid this problem?
Two solutions I have employed (but both seem like they won't scale up very well in real-world applications):
1. When updating the Game, iterate over all players targets and update them with the new Target values (possibly by checking reference equality "eq" for seeing which was which in a particular time step).
2. Give Target a new identifier field, and Player has a copy of TargetID instead of Target.
Thanks again for your thoughts!
Sam
On Friday, June 1, 2012 3:51:48 PM UTC-6, Vlad Patryshev wrote:
Hi Sam,
While lenses may be the right answer, I got a feeling that the way you formulate the problem, the relationship must be more complicated.
Are there players that don't play anything? Are there players that play more than one game?