2

As I know so far, Ruby is the only mainstream language that supports both call/cc and try/catch/finally (written as begin/rescue/ensure/end block).

I am not familiar with Ruby, but my intuitive tell me that there are potential conflicts of that two, since call/cc allows arbitrarily control flow and ensure require some guaranteed control flow (some code path MUST be executed in a pre-defined situation, namely leaving the containing block).

So, are there any conflicts exists in the language? if so what is the defined behavior of the language in such a case? Especially, what happen if call/cc being used in a begin/ensure block or in the ensure/end block? What if calling a captured call/cc after the block contains ensure clause?

Earth Engine
  • 10,048
  • 5
  • 48
  • 78

1 Answers1

4

In Ruby you have callcc, throw / catch and raise / rescue / ensure.

throw terminates the block with ensure begin executed:

catch(:done) {
  begin
    puts "before"
    throw :done
    puts "after"  # will not be called
  ensure
    puts "ensure"
  end
}

produces:

before
ensure

callcc terminates the block with ensure begin skipped:

callcc { |cc|
  begin
    puts "before"
    cc.call
    puts "after"   # will not be called
  ensure
    puts "ensure"  # will not be called
  end
}

produces:

before

Another example storing the Continuation object inside a global variable:

begin
  puts "before"
  callcc { |cc| $cc = cc }
  puts "after"
ensure
  puts "ensure"
end

$cc.call

produces:

before
after
ensure
after
ensure
after
...
Stefan
  • 109,145
  • 14
  • 143
  • 218
  • OK, so what if I use `callcc` to jump into the `begin` block or even the `ensure` block? – Earth Engine Jun 11 '13 at 22:29
  • You cannot jump to an arbitrary position, `cc.call` always jumps to the end of the `callcc { }` block. – Stefan Jun 12 '13 at 06:18
  • I mean, what if I put a `callcc` block INSIDE the `begin/end` block, return a function (with the continuation variable) from inside, and then call that function from outside, to jump inside the block? – Earth Engine Jun 12 '13 at 06:50
  • So the conclusion is, `callcc` has more priority than `ensure`, `ensure` can only ensure execution if there is no `callcc` exists. – Earth Engine Oct 05 '17 at 04:26