Functional Programming, Immutable Classes and References

41 views
Skip to first unread message

Sam Reid

unread,
Jun 1, 2012, 12:31:23 PM6/1/12
to scala...@googlegroups.com
Scala community,

I am having a functional programming problem I thought you could help out with.  Let's say I have immutable case class for Player and Target, and I want to know when the Player has reached the Target.  Players can have different Targets and the Targets can move.  In functional programming, where is the best place to keep track Player/Target relationships?  In imperative programming, I would just give the Player a reference to the mutable Target.  But in functional/immutable programming, when I am creating a new model state in which the Target positions are different, it seems like it would be a lot of brittle bookkeeping (not practically scalable) to go through and update all of the Player Target references as well.  I have tried experimenting with creating a family of *Id classes (like TargetID), so that the Player has a reference to a TargetID, and a TargetID can be used to fetch the Target from the model, but as I am adding more types of things, I am also concerned about the scalability of this approach.

How would you solve or avoid this problem?

Thanks!
Sam

Tony Morris

unread,
Jun 1, 2012, 12:36:13 PM6/1/12
to scala...@googlegroups.com

Vlad Patryshev

unread,
Jun 1, 2012, 5:51:48 PM6/1/12
to tmo...@tmorris.net, scala...@googlegroups.com
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?

Thanks,
-Vlad

Sam Reid

unread,
Jun 1, 2012, 9:11:49 PM6/1/12
to scala...@googlegroups.com, tmo...@tmorris.net
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?

Thanks,
-Vlad

Tony Morris

unread,
Jun 1, 2012, 9:14:54 PM6/1/12
to Sam Reid, scala...@googlegroups.com, tmo...@tmorris.net
On 02/06/12 11:11, Sam Reid wrote:
> 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?
You use a multi-lens for and the multi-modify operation for that. The
paper doesn't cover it, sorry. Most of the available reading material
uses haskell. Happy to help you in this regard.
Reply all
Reply to author
Forward
0 new messages