windweller
windweller

Reputation: 2385

Delayed Execution of a series of operations

I'm trying to write a class where when you call a function defined in the class, it will store it in an array of functions instead of executing it right away, then user calls exec() to execute it:

class TestA(val a: Int, newAction: Option[ArrayBuffer[(Int) => Int]]) {
  val action: ArrayBuffer[(Int) => Int] = if (newAction.isEmpty) ArrayBuffer.empty[(Int) => Int] else newAction.get
  def add(b: Int): TestA = {action += (a => a + b); new TestA(a, Some(action))}

  def exec(): Int = {
    var result = 0
    action.foreach(r => result += r.apply(a))
    result
  }

  def this(a:Int) = this(a, None)
}

Then this is my test code:

  "delayed action" should "delay action till ready" in {
    val test = new TestA(3)
    val result = test.add(5).add(5)
    println(result.exec())
  }

This gives me a result of 16 because 3 was passed in twice and got added twice. I guess the easy way for me to solve this problem is to not pass in value for the second round, like change val a: Int to val a: Option[Int]. It helps but it doesn't solve my real problem: letting the second function know the result of the first execution.

Does anyone have a better solution to this?? Or if this is a pattern, can anyone share a tutorial of it?

Upvotes: 0

Views: 146

Answers (1)

Siphor
Siphor

Reputation: 2534

Just save the result of the action in the 'result' variable (instatiate it with 'a') and use the previous result as input for the current iteration

def exec(): Int = {
    var result = a
    action.foreach(r => result = r.apply(result))
    result
}

or use the more functional oriented solution that does the same

def exec(): Int = {
    action.foldLeft(a)((r, f) => f.apply(r))
}

Upvotes: 1

Related Questions