user3167003
user3167003

Reputation:

How to use Scala's immutable data structures as members of a class

I'm trying to get a hold on FP and the concept of immutable data structures for mutable states. Though i get the idea "locally" like in a function, i don't understand how i would do it in a system.

I thought of an example to make it clear: So in case i wanted to model a simple CPU-Scheduler for example, i would imagine doing so by constructing a class CPU with two members: a list of processes in line for processing, and a current process.

class CPU ( pending: List[Process], p:Process)

Additionally i would need some method like next() to change the current process. So now, how would i do that with immutable variables? Since pending and p are fixed, i can not reassign them.

Upvotes: 2

Views: 335

Answers (2)

Arne Claassen
Arne Claassen

Reputation: 14404

Once you work with immutable data, the mental model changes from "how do I change this?" to "how do I transform this?"

For you specific scenario, you'd want to add methods that can produce a new copy of CPU with the specific changes. Fortunately, using case classes, Scala does most of it for you by providing a copy method.

Now in your case, I'll assume that next should remove the next Process from pending and set it as p. I'll further presume that you might want the finished process returned as well for some book-keeping. In this case, all members are being touched, so it's easier to just create a new instance instead of using copy:

case class Process()

case class CPU(pending: List[Process], p: Process) {
  def next(): (Process, CPU) = (p, CPU(pending.tail, pending.head))

  def add(process: Process) = this.copy(pending = process :: pending)
}

val cpu = CPU(Process()::Nil,Process())
val cpu1 = cpu.add(Process())
val (finished,cpu2) = cpu.next()

For good measure I added add to illustrate the use of copy.

With this CPU is immutable and can be transformed into other forms. Your scheduler would likely still require a var to keep the current state of CPU, but that's another topic to tackle.

Now your the question might be, why is this desirable. One reason is that your data is now safe to pass around and be accessed from any thread, since it can never change and requires no synchronization. By going immutable on your data, the only synchronization you need is around processes that transform, rather than around the data itself and anyone that gets an instance of your data can be sure that it will never change from under them, but represent a snapshot in time when they asked for the data.

Upvotes: 3

Andrey Tyukin
Andrey Tyukin

Reputation: 44918

Scala does not force you to make everything immutable. If you have a component that has a changing state, it's perfectly fine to model its state by mutable data structures (or immutable structures assigned to vars). The important thing is that you don't share mutable state between multiple complicated components, and use immutable fire-and-forget messages for communication instead.

Depending on how you set up your simulation of the CPU-Scheduler, you might also make it immutable. Then you would have to define the state transitions outside of the CPU-Scheduler, and store immutable instances of the CPU-Scheduler that represent your state. That would mean, that you have to create a new instance of the CPU-Scheduler in each iteration (this can be very cheap if you use the right structures).

Upvotes: 1

Related Questions