Семантика вызовов /cc и "обеспечить" в Ruby

Насколько я знаю, Ruby - единственный основной язык, который поддерживает call/cc а также try/catch/finally (написано как begin/rescue/ensure/end блок).

Я не знаком с Ruby, но мой интуитивный говорит мне, что есть потенциальные конфликты этих двух, так как call/cc позволяет произвольно контролировать поток и ensure требует некоторого гарантированного потока управления (некоторые пути кода ДОЛЖНЫ выполняться в заранее определенной ситуации, а именно, выходя из содержащего блока).

Итак, существуют ли конфликты в языке? если так, каково определенное поведение языка в таком случае? Особенно, что произойдет, если call/cc используется в begin/ensure блок или в ensure/end блок? Что делать, если звонить захваченному call/cc после того, как блок содержит ensure статья?

1 ответ

Решение

В Ruby у вас есть callcc, throw / catch а также raise / rescue / ensure,

throw завершает блок с ensure начать исполняться:

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

производит:

before
ensure

callcc завершает блок с ensure начать пропущено:

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

производит:

before

Еще один пример хранения Continuation объект внутри глобальной переменной:

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

$cc.call

производит:

before
after
ensure
after
ensure
after
...
Другие вопросы по тегам