Для сравнения его с C текущее продолжение похоже на текущее состояние стека. Это имеет все функции, ожидающие результата текущей функции для окончания так, они могут возобновить выполнение. Переменная, полученная как текущее продолжение, используется как функция, за исключением того, что это принимает обеспеченное значение и возвращает его стопке ожидания. Это поведение подобно функции C longjmp, куда можно возвратиться для понижения частей стека сразу.
(define x 0) ; dummy value - will be used to store continuation later
(+ 2 (call/cc (lambda (cc)
(set! x cc) ; set x to the continuation cc; namely, (+ 2 _)
3))) ; returns 5
(x 4) ; returns 6
Одно основное отличие между стеком C и продолжением - то, что продолжение может использоваться в любой точке в программе, даже если состояние стека изменилось. Это означает, что можно по существу восстановить более ранние версии стека и использовать их снова и снова, ведя к некоторому уникальному процессу выполнения программы.
(* 123 (+ 345 (* 789 (x 5)))) ; returns 7
reason: it is because (x 5) replaces the existing continuation,
(* 123 (+ 345 (* 789 _))), with x, (+ 2 _), and returns
5 to x, creating (+ 2 5), or 7.
способность сохранить и восстановить состояние программы имеет много общего с многопоточностью. На самом деле можно реализовать собственный планировщик потока с помощью продолжений, поскольку я попытался проиллюстрировать здесь .
class Builder
def initialize
@lines = []
end
def lines(&block)
block_given? ? instance_eval(&block) : @lines
end
def add_line( text )
@lines << text
end
end
my_builder = Builder.new
my_builder.lines {
add_line "foo"
add_line "bar"
}
p my_builder.lines # => ["foo", "bar"]
Вы также можете использовать использование метода в лучших практиках Ruby с использованием длины аргументов с арностью:
class Foo
attr_accessor :list
def initialize
@list=[]
end
def bar(&blk)
blk.arity>0 ? blk.call(self) : instance_eval(&blk)
end
end
x = Foo.new
x.bar do список << 1 список << 2 список << 3 конец
x.bar do | foo | foo.list << 4 foo.list << 5 foo.list << 6 end
помещает x.list.inspect