Семантика вызовов /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
...