Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a counter in functional programming way

While trying to understand companion objects, I have written following code which counts the number of times a class was instantiated. I had to use a 'var' to keep the count. Is there a 'functional programming' way to achieve the same task i.e. use immutable variables.

class C {
  C.counter+=1
  def someCFunction = {println ("some C function. Counter is "+C.counter)}
}

object C{
  var counter:Int=0 //I do not want to use var
}

val c1 = new C
c1.someCFunction

val c2 = new C
c2.someCFunction
like image 497
Manu Chadha Avatar asked Nov 30 '16 19:11

Manu Chadha


Video Answer


1 Answers

This is a good use case for the State Monad. Instead of modifying a variable in place, you create a new value, and pass it around.

import cats.data.State
class C {}
object C { val counter: State[Int, Unit] = State.pure() }

def createNewC: State[Int, C] = {
  // increment the count, and return a new instance of C
  C.counter.modify(_ + 1).map(_ => new C)
}

val countAll = for {
  c0 <- createNewC
  c1 <- createNewC
  c2 <- createNewC
  c3 <- createNewC
} yield {
  // use your instance of C in here
  ()
}

// actually run your program, start the counter at 0
countAll.run(0).value._1 // 4

Note: State here comes from the Cats project.

like image 134
soote Avatar answered Sep 21 '22 04:09

soote