Continuation 클래스

Continuation 클래스

Continuation 객체는 continuationrequire한 뒤 Kernel#callcc로 만들어져요. 반환 주소와 실행 컨텍스트를 품고 있어서, 프로그램 어디서든 callcc 블록의 끝으로 비지역적(nonlocal) 반환을 할 수 있게 해 줘요. C의 setjmp/longjmp를 구조화한 것과 비슷하다고 볼 수 있는데, 상태를 더 많이 담으니 스레드에 더 가깝다고 생각해도 돼요.

출처: Ruby 4.0 API

본문

ContinuationKernel#callcc 로 생성돼요. 반환 주소와 실행 컨텍스트를 담고 있어, 프로그램 어디서나 callcc 블록의 끝으로 비지역적 반환을 할 수 있게 해 줘요. 이는 C 의 setjmp/longjmp 를 구조화한 버전과 유사하다고 볼 수 있어요 (그래도 더 많은 상태를 포함하므로 스레드에 더 가깝다고 생각할 수 있어요).

예를 들어:

require "continuation"
arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
callcc{|cc| $cc = cc}
puts(message = arr.shift)
$cc.call unless message =~ /Max/

출력:

Freddie
Herbie
Ron
Max

callcc를 다른 메서드 안에서도 호출할 수 있어요:

require "continuation"

def g
  arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
  cc = callcc { |cc| cc }
  puts arr.shift
  return cc, arr.size
end

def f
  c, size = g
  c.call(c) if size > 1
end

f

이 (다소 인위적인) 예시는 안쪽 루프가 처리 중간에 일찍 포기하도록 만들어 줘요:

require "continuation"
callcc {|cont|
  for i in 0..4
    print "#{i}: "
    for j in i*5...(i+1)*5
      cont.call() if j == 17
      printf "%3d", j
    end
  end
}
p