0

Scala newbie trying to implement a method named "counter" whose method signature is below.

The method should be a stateless function so that when it is invoked with integer n, it returns a stateful function. This stateful function should return n when it is first called, then n + 1, then n + 2, etc.

The counters must be independent such that running counter(1) twice yields two functions that do not interfere with each other's state.

Below is what I have so far:

val counter : Int => () => Int = {
   // Complete definition below.
   var count = 0

   n: Int => () => {
       var returnVal = n + count
       count = count + 1
       returnVal
   }
}

An example of how counter is called:

  assert ({ 
     val k1 : () => Int = counter (1)
     val k2 : () => Int = counter (2)
     val r1 : Int = k1 ()
     val r2 : Int = k1 ()
     val r3 : Int = k2 ()
     val r4 : Int = k2 ()
     val r5 : Int = k2 ()
     val r6 : Int = k1 ()
     (r1, r2, r3, r4, r5, r6)
  } === (1, 2, 2, 3, 4, 3)
  )

When running the assert, my implementation of counter returns (1, 2, 4, 5, 6, 6).

I believe this is due to k1 and k2 both pointing to the same count variable. However, I can't figure out how I would provide k1 and k2 their own separate count variable so that they "do not interfere with each other's state", as per the requirements.

Am I on the right track? Any guidance would be most appreciated.

shoogazer
  • 157
  • 2
  • 9

2 Answers2

2

First, check out the difference between def and val. The TL;DR of it is that val will only evaluate once, so you can't really depend on a count-holding variable if you define it in counter before you get to the function you want to return.

To make it clearer, I added parenthesis to make the pattern matching more obvious and broke apart that line because we needed to capture the parameter that was passed-in to counter and store it in the closure for the anonymous function we are returning.

val counter : Int => () => Int = {
  (n: Int) => {
    var count = n

    () => {
      val returnVal = count
      count = count + 1
      returnVal
    }
  }
}
Community
  • 1
  • 1
bergren2
  • 44
  • 1
  • 6
1

You need to change the keyword from val to def for the counter method you are defining:

def counter : Int => () => Int = {
   // Complete definition below.
   var count = 0

   n: Int => () => {
       var returnVal = n + count
       count = count + 1
       returnVal
   }
}

Because with val, the count variable is only defined once which happens when you define the counter method, so later on all the closures will share this variable; with def method, the count variable will be redefined every time you call counter(n).


It's easier to see this if you add a println after the var count = 0 line:

scala> val counter : Int => () => Int = {
          // Complete definition below.
          var count = 0
          println(count)

          n: Int => () => {
              var returnVal = n + count
              count = count + 1
              returnVal
          }
       }

0                                           // 0 is printed here
counter: Int => (() => Int) = <function1>

scala> val k1 = counter(1)                  // nothing prints here
k1: () => Int = <function0>

scala> val k2 = counter(2)                  // nothing prints here
k2: () => Int = <function0>
Psidom
  • 209,562
  • 33
  • 339
  • 356
  • Thanks, that makes more sense. Unfortunately, I have to keep the val keyword as per the guidelines of the assignment. – shoogazer Feb 19 '17 at 04:31