본 포스팅은 후속문 자체의 정의와 설명에 관한 내용이 아니므로
후속문의 개념은 너무나도 잘 쓰여진 아래 링크 참조 (거의 유일한 한글자료이자 아주 상세하게 쓰여진 자료)
Computat ergo est: 후속문(Continuation) : 제1부. 개념과 call/cc (guruma.github.io)
Delimited Continuations 이 무엇인지 파악하기 위하여 Continuations(후속문) 을 개념적인 Level 에서 훑어 보자
CPS (Continuations Passing Style)
흔히 callback 이라고 부르는 방식이다.
Continuations (후속 작업을) Passing(넘기는) Style(스타일)
First-Class Continuation
후속문 자체를 1급 시민으로 다룰수 있으면 그 언어는 First-Class Continuation 을 지원한다고 볼수있다.
그럼 여기서 거의 모든 언어가 CPS 를 지원하니까 전부 First-Class Continuation 인가? 하면 아니다.
우리는 Function을 1급 시민으로 다룬것 뿐이다. 후속문 그 자체를 다루지는 않았다.
Continuation
후속문은 다음에 할 작업이다.
- If문은 A/B 후속문중 하나만 선택하는것이다.
- Error 발생 - Catch 는 아래 있는 모든 후속문을 무시하고 Catch 안의 내용을 후속문으로 선택하는것이다
- For 문은 같은 후속문을 반복해서 선택하는것이다.
- Break 는 반복작업할 후속문은 무시하고 For문 밖의 후속문을 선택하는것이다.
즉 CPS 는 Function 이 끝나면 호출될 다음 후속문을 Function으로 넘긴것뿐이다.
후속문을 다룬다는건 무엇을 의미하는가?
제어 흐름방식 그자체를 다룬다는것을 의미한다.
예를 들어보면 다음과 같은 언어가 존재한다고 해보자 이름은 흠.. NoAbort Lang 이다
- For/ForEach 문이 존재함
- If 문이 존재함
- Break 문 없음
- Return 문 없음
위와 같은 언어에서
Int 형 List 를 받고 List 를 처음부터 끝까지 순회하면서 출력하는데, 순회하다가 10 이라는 Item 을 만나면 즉시 종료하는 함수를 짠다고 해보자
다른 언어라면 이렇게 짤수있다.
for(var item in items) {
if (item == 10) {
return // 혹은 break
}
println(item)
}
하지만 우리 NoAbort Lang 언어에서는 break 도 없고 return 도 없다.
따라서 저런 전통적인 방법으로 구현하는게 불가능하다.
하지만 만약 NoAbort Lang 이 First-Class Continuation 인 언어라면?
개발자가 Break나 Return 에 해당하는 Continuation 제어 구조를 직접 구현해서 중간에 abort 시키는것이 가능하다.
// 대충 이런식..
with-current-continuation (return) {
for(var item in items) {
if (item == 10) {
return // 혹은 break
}
println(item)
}
}
call/cc
First-Class Continuation 인 경우 거의 대부분 위 코드의 with-current-contiunation 같은 게 존재한다.
그걸 거의 모든 경우 call/cc 라고 한다 (call/with-current-contiunation)
call/cc 를 이용하여 후속문을 First-Class Continuation 로 다룰수있는것
Context
후속문을 컨트롤할때 중요한것은 Context 이다. 간단하게는 Call Stack 이라고 보면 되고
기본적으로는 Call Stack Context 는 1개 뿐이다.
함수 콜이 되면 Call Stack 에 해당 함수에 대한 Layer 가 쌓이는것 뿐이다.
Error 가 발생하고 Catch 가 되는 경우, 스택 되감기를 통하여 Catch 까지 타고 올라가고 Catch 안의 내용이 다음 후속문으로 선택되는것이다. 즉
- (A - B) : A 함수에서 B 호출
- (A - B - C) : B 함수에서 C 호출
- (A - B - C) : C 함수에서 Exception 발생
- (A - B) : 스택 되감기중
- (A) : A 에서 Catch
- (A) : Catch 할때에는 C 의 Context 는 몰?루?, 아는것은 오로지 넘겨받은 Exception e 뿐
이것이 일반적인 프로그램이 돌아가는 구조이다.
반면 후속문을 call/cc 로 컨트롤하게 되는 경우는 다르다.
call/cc 를 이용하면 해당 후속문에 해당하는 Context 로 완전 대체 된다.
- (A - B) : A 함수에서 B 호출
- (A - B - C) : B 함수에서 call/cc 로 후속문 선택
- (I' - J' - K'): 선택된 후속문의 Context 로 완전 대체
여기까지가... 기존에 학습한 Continuation 내용이다.
Delimited Continuation
구분된 후속문이 대체 뭔데?
language agnostic - Difference between delimited and undelimited continuations - Stack Overflow
scheme - What exactly is a "continuation prompt?" - Stack Overflow
간단하게 말하자면, Context 가 완전 대체 되는것이 아니라, 내 원하는 만큼만 구분되서 (Delimited) 컨트롤할수 있는 후속문을 의미한다.
즉 Context 를 일부만 캡쳐한다
- (A - B) : A 함수에서 B 호출
- (A - B - C) : B 함수에서 Delimited Continuation 선택
- (A - B - I' - J'): 구분된 Context 만 대체 (혹은 사용)
예를 들어 코루틴은 일반적으로 진입점이 여러개인 서브루틴이고, yield로 기존 중지점부터 시작한다 (=> 코루틴별 Context 가 있음)
- (A - B) : A 함수에서 B 호출
- (A - B - C1.1) : B 함수에서 C1 코루틴 선택
- (A - B): C1 Yield
- (A - B - C2.1): C2 코루틴 선택
- (A - B): C2 Yield
- (A - B - C1.1 - C1.2) : B 함수에서 C1 코루틴 선택
'프로그래밍 기술 노트 > Functional Study' 카테고리의 다른 글
[함수형 미세 팁] 파라미터 3개 이상의 Function 으 로 Reduce 하기 (1) | 2022.12.09 |
---|---|
[liftIO] 빠르게 올리는 함수형 컨퍼런스 liftIO 2022 후기 (0) | 2022.12.03 |
[Monad] 시퀀스를 여행하는 모나드를 위한 안내서 (1) | 2022.10.09 |
[HKT] Value / Type / Kind 와 Higher Kinded Type (Feat. 고차함수) (1) | 2022.04.30 |
[Expression Problem] 객체 대수 (Object algebras) 와 Tagless Final (0) | 2022.04.28 |