Jong-Chan Choi 님 말씀대로 대부분의 코루틴 구현은 continuation을 사용하는 것 같고.. 근본적으로 인간은 순차적 사고에 익숙하지만 사실 실제 함수형 프로그래밍은 순서와는 관계가 없죠.오직 값 사이의 dependency가 정의되면 그에 따라 컴파일러가 의미가 통하는 바이너리를 만들어줄 뿐입니다. 그 의미적인 갭(순서와 함수간의 데이터 의존성 사이의 관계)을 채워주는 부분으로 monad가 있습니다. 재미있는건 상태, IO, continuation 등은 프로그래밍 언어에서 모두 따로 발전이 이뤄졌는데 나중에 들여다 보니 모두 다 monadidc 구조를 가진 물건들이라는걸 알게 됐죠. 아마도 (제 개똥 철학입니다) 이는 프로그램을 이루는 각 요소들이 순서대로 결합되서 사용되기 위해서는 한 값에서 어떤 구조를 만들어내고(unit), 값 사이의 변환(매핑)으로부터 구조 사이의 변환(매핑)을 끌어내는(바인드) 기능이 필수적이기 때문에 생기는 일이 아닌가 싶습니다.
컨티뉴에이션은 기본적으로는 함수의 호출 형태를 제한하고 모든 데이터와 제어 흐름을 명시적으로 드러내게 만든 것입니다. 이 개념이 순차어에서 각 명령을 입력과 출력으로 나누고, goto를 모든 지점에 명시한다고 생각해 보면 그렇게 복잡하지 않게 이해할 수도 있는데, 함수 형태로 표현하면 함수 개수가 늘어나면서 복잡해 보입니다. 답글에 자세히 쓰긴 좀 그렇고.. 나중에 기회가 되면 ^^ 어쨌든 컨티뉴에이션을 도입하고 1급 함수와 합쳐지면 재밌는 일이 벌어지는데, “내 프로그램이 이 지점 이후에 할 일”을 함수에 담아둘 수 있기 때문에 흐름을 가지고 여러가지 장난을 칠 수 있게 되는거죠. 유닉스의 setjmp/longjmp를 아는 분들은 그와 비슷한 장난이 가능하다고 생각할 수도 있습니다. 대표적인건 예외처리(정상 흐름과 비정상 흐름을 각각 별도의 컨티뉴에이션 함수로 분리해서 예외 상황에는 예외쪽 컨티뉴에이션을, 아닌 상황에는 정상 컨티뉴에이션을 호출), 코루틴(yield시 다른쪽 함수의 컨티뉴에이션을 호출) 등이 있죠.
어떤 언어든 쓰레드와 락 등을 사용해 할 수 없는 일을 코루틴이 대신해주지는 못하는 것 같습니다(수학적인 증명이 있는지는 모르겠습니다). 다만 명령형 언어에서는 아무래도 콜백을 사용한 비동기 코딩이나 상태머신이나 통신 채널, 락 등등의 다른 방식을 사용하는 것보다는 코드가 간결해지고 이해하기 편한 면이 있는 것 같습니다. 함수형 언어는 언어 특성상 코루틴 같은 요소의 쓸모가 더 적다고 할 수 있을 것 같아요. 다만 모나드가 IO 등 선후관계가 중요한 경우에 유용하게 쓰이듯이 코루틴도 프로그램 흐름을 명시적으로 제어해야 할 경우 쓸모가 있을 것 같습니다. 그리고 컨텍스트 스위칭이 필요 없는 경량 스레드 역할을 할 수 있다는 코루틴의 특징을 살리면 명령의 순차적인 실행이 필요하고 둘 이상의 제어 흐름이 서로 섞여야 하는 경우 함수형 언어에서도 코루틴이 쓸모가 있겠죠.
예전 모듈라2 나왔을 때 코루틴을 사용해 여러 자동차가 움직이는걸 보여주는 시뮬레이션이 마소에 실린 적이 있는데 인상적이었죠. UCSD 파스칼 컴파일러에서 p-코드를 돌려주는 VM을 사용했는데 망했고, 자바가 JVM을 채택하면서는 성공하고. 코루틴도 최근 각광받는거 보면 세상은 돌고 도는 것 같습니다. 조상의 빛난 얼을 오늘에 되살려… 일까요? ^^