Continuation 클래스

Continuation 클래스

Continuation 객체는 continuationrequire한 뒤 Kernel#callcc로 생성돼요. 이 객체는 복귀 주소와 실행 컨텍스트를 담고 있어서, 프로그램 어디에서든 callcc 블록의 끝으로 비지역 반환(nonlocal return)을 할 수 있게 해줘요. 연속은 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
}
puts

이 코드는 다음과 같이 출력해요:

0: 0 1 2 3 4
1: 5 6 7 8 9
2: 10 11 12 13 14
3: 15 16

출처: Ruby 3.3 API

본문

인스턴스 메서드

  • cont[args, ...] (call의 별칭) — 연속을 호출해요. 프로그램은 callcc 블록의 끝에서부터 이어서 실행돼요. 인자가 없으면 원래 callccnil을 돌려주고, 인자가 하나면 그 값을, 그 외에는 인자를 담은 배열을 돌려줘요.
callcc {|cont| cont.call } #=> nil
callcc {|cont| cont.call 1 } #=> 1
callcc {|cont| cont.call 1, 2, 3 } #=> [1, 2, 3]
  • call(args, ...) — 인자와 함께 연속을 호출하는 메서드예요. []라고도 별칭이 붙어 있어요.