0

Starting from this answer:

Scala continuation and exception handling

I would like to know if there is a way to re-execute the ENTIRE try block (or ctry block in the example code) after the exception is handled.

What I mean is if the resume() operation could move the execution to the first statement of the try block instead of simply resuming the execution from the statement that raised the exception.

Thanks a lot!

Community
  • 1
  • 1
Niko P
  • 41
  • 1
  • 3
  • 3
    I think it's called a "loop". – n. m. could be an AI Sep 07 '11 at 09:30
  • Ok, next question. Suppose the try block raises an exception. In the catch block I change the code within the try block (using bytecode or recompiled source code). There is a way to re-execute the NEW try block? – Niko P Sep 07 '11 at 09:35
  • 1
    @Niko - I don't understand what you mean by changing the code within the catch block. Are you dynamically reloading the class definition within the application, while the program sits inside that class? It's not obvious how you'd do this (or whether this is what you mean) so more detail would be very helpful. – Andrzej Doyle Sep 07 '11 at 11:24

1 Answers1

0

Here's a silly example that I think will steer you toward an answer:

object Retry

object SO_7331489 extends App {

  import scala.util.continuations._

  var dividend: String = "ten"
  var divisor: Int = 0

  val quotient = reset {

    shift { k: (Unit => Any) =>
      def retry: Any =
        k() match {
          case Retry => retry
          case x     => x
        }
      retry
    }

    try {
      dividend.toInt / divisor
    } catch {
      case e: java.lang.NumberFormatException =>
        println("caught " + e.getClass.getName + "(" + e.getMessage + ")")
        dividend = "10"
        println("retrying with dividend = \"10\"")
        Retry
      case e: java.lang.ArithmeticException =>
        println("caught " + e.getClass.getName + "(" + e.getMessage + ")")
        divisor = 2
        println("retrying with divisor = 2")
        Retry
      case t: Throwable =>
        println("caught " + t.getClass.getName + "(" + t.getMessage + ")")
        // Nothing left to retry, so don't return Retry
    }

  }

  println("quotient: " + quotient)

}

The idea is to trigger the shift block before your try/catch block. Within the catch block, if you want to retry the whole thing, simply return the Retry object.

It might be nice to pull the entire shift block out into a simple function (e.g. retry), but I left it inline for clarity.

This code produces the following output:

[info] Running SO_7331489 
caught java.lang.NumberFormatException(For input string: "ten")
retrying with dividend = "10"
caught java.lang.ArithmeticException(/ by zero)
retrying with divisor = 2
quotient: 5
earldouglas
  • 13,265
  • 5
  • 41
  • 50