코 루틴 대 연속 대 발전기


147

코 루틴과 연속체와 발전기의 차이점은 무엇입니까?


2
코 루틴과 연속체가 실제로 동등한 지 궁금합니다. 연속으로 코 루틴을 모델링하는 것이 가능하다는 것을 알고 있지만 연속성이 더 강력하기 때문에 코 루틴으로 연속을 모델링 할 수 있습니까?
nalply

답변:


127

생성기부터 시작하겠습니다. 가장 간단한 경우입니다. @zvolkov가 언급했듯이 반환하지 않고 반복적으로 호출 할 수있는 함수 / 객체이지만 호출되면 값을 반환 (수율) 한 다음 실행을 일시 중단합니다. 그들이 다시 부름을 받으면, 그들은 마지막으로 실행을 중단 한 곳에서 시작하여 다시 일을합니다.

발전기는 본질적으로 컷 다운 (비대칭) 코 루틴입니다. 코 루틴과 생성기의 차이점은 코 루틴이 처음 호출 된 후 인자를 받아 들일 수 있지만 생성기는 할 수 없다는 것입니다.

코 루틴을 사용하는 곳의 사소한 예를 생각해내는 것은 약간 어렵지만 여기에 최선의 노력이 있습니다. 이 (구성된) 파이썬 코드를 예로 들어 보자.

def my_coroutine_body(*args):
    while True:
        # Do some funky stuff
        *args = yield value_im_returning
        # Do some more funky stuff

my_coro = make_coroutine(my_coroutine_body)

x = 0
while True:
   # The coroutine does some funky stuff to x, and returns a new value.
   x = my_coro(x)
   print x

코 루틴이 사용되는 예는 렉서 및 파서입니다. 언어에 코 루틴이 없거나 어쨌든 에뮬레이션이 없으면 lexing 및 parsing 코드는 실제로 두 가지 별도의 우려 사항이더라도 함께 혼합해야합니다. 그러나 코 루틴을 사용하면 렉싱 및 구문 분석 코드를 분리 할 수 ​​있습니다.

(저는 대칭 코 루틴과 비대칭 코 루틴의 차이점을 해결하려고합니다. 그것들이 동등하고 다른 것으로 변환 할 수 있으며, 비대칭 코 루틴 (발전기와 가장 유사한 것)은 파이썬에서 비대칭 코 루틴을 구현하는 방법을 간략히 설명했습니다.)

연속은 실제로 아주 단순한 짐승입니다. 그것들은 모두 프로그램의 다른 지점을 나타내는 함수이며, 호출하면 함수가 나타내는 지점으로 실행이 자동으로 전환됩니다. 당신은 그것을 깨닫지 않고 매일 매우 제한된 버전을 사용합니다. 예를 들어 예외는 일종의 인사이드 아웃 연속으로 생각할 수 있습니다. 계속해서 파이썬 기반의 의사 코드 예제를 드리겠습니다.

파이썬에이라는 callcc()함수가 있고이 함수에는 두 개의 인수가 있는데, 첫 번째는 함수이고 두 번째는 호출 할 인수 목록입니다. 해당 함수에 대한 유일한 제한은 마지막 인수가 함수 (현재의 연속 임)가 될 것입니다.

def foo(x, y, cc):
   cc(max(x, y))

biggest = callcc(foo, [23, 42])
print biggest

무엇 일어날 것은 즉 callcc()에서 전화를 켜 것이 foo()현재 계속 (과 cc), 즉, 프로그램의 시점에 참조하는 callcc()불렸다. foo()현재 연속을 호출 할 때 현재 연속을 호출하는 callcc()값으로 반환하도록 지시 하는 것과 본질적으로 동일하며 , 그렇게하면 스택을 현재 연속이 작성된 위치 (예 : 호출 한 시점)로 롤백합니다. callcc().

이 모든 결과는 가상의 파이썬 변형이 인쇄 될 것 '42'입니다.

나는 그것이 도움이되기를 희망하며, 내 설명이 상당히 개선 될 수 있다고 확신합니다!


6
하나의 nit : 구분 된 연속은 기능이지만, 제한되지 않은 연속은 아닙니다 : okmij.org/ftp/continuations/undelimited.html#delim-vs-undelim
Frank Shearar

2
그건 좋은 지적이야. 즉, 대부분의 실제 응용 프로그램에서 사람들이 '연속'이라고 말하면 부분 / 구분 연속에 대해 이야기하고 있습니다. 다양한 다른 종류의 연속을 가져 오는 것은 설명을 다소 어지럽 혔을 것입니다.
Keith Gaughan

1
연속은 기능으로 구체화 될 수 있지만 기능은 아닙니다. "이는 대부분의 실제 응용 분야에서 사람들이 '계속'이라고 말하면 부분 / 구분 된 연속에 대해 이야기하고 있습니다." "계속"이라는 용어를 사용 하시겠습니까? 나는 그런 사용법을 결코 만난 적이 없다. 또한 call / cc를 사용하여 무제한 연속 예제를 제공했습니다. 구분 된 연속 연산자는 일반적으로 "재설정"및 "시프트"(다른 이름을 가질 수 있음)입니다.
Ivancho

3
내가 쓴지 5 년 이라는 사실부터 시작하겠습니다 . 당신은 파티에 다소 늦었습니다. 둘째, 나는 무제한 연속이 기능하지 않는다는 것을 알고 있지만, 언어를 간단하게 유지하면서 그것들을 참조하지 않고 작동 방식을 설명하려고합니다. 일반 프로그래머의 관점에서 볼 때 무제한 연속이 반환되지 않는다는 사실은 함수를 원샷 함수로 만들 뿐이며 함수 의 정의에 따라 정확 하지 않지만 적어도 이해할 수는 있습니다.
Keith Gaughan

2
이것이 "coroutine vs generator"를 검색 할 때 Google에서 얻은 첫 번째 결과이므로 파티에 늦지 않았습니다. 나는 그들의 차이점에 대한 좋은 정보를 찾고 싶었다. 어쨌든 나는 다른 곳에서 찾았습니다. 그리고 나는 연속에 대한 당신의 설명이 잘못되었다는 것을 처음으로 지적한 것은 아닙니다. 문제는 누군가가 잘못 알고 나중에 다른 단어에 사용 된 것과 같은 단어를 만나면 혼란스러워한다는 것입니다.
Ivancho

33

코 루틴은 교대로 작업을 수행 한 다음 그룹의 다른 코 루틴을 제어하기 위해 일시 ​​중지하는 몇 가지 절차 중 하나입니다.

계속은 일부 프로 시저로 전달되는 "함수를 가리키는 포인터"로, 해당 프로 시저가 완료 될 때 실행됩니다 ( "계속").

Generator (.NET)는 값을 내뱉고 메소드의 "일시 정지"한 다음 다음 값을 요청할 때 같은 지점에서 진행할 수있는 언어 구성입니다.


나는 대답이 정확하지 않을 수도 있지만이 수준의 질문에서는 간단하게 유지하려고 노력했습니다. 게다가, 난 정말이 모든 자신 :) 이해하지 않는다
zvolkov

파이썬의 제너레이터는 C # 버전과 비슷하지만 반복자 객체의 인스턴스를 생성하기위한 특수 구문으로 구현되어 제공하는 "함수"정의에 의해 반환 된 값을 반환합니다.
Benson

2
작은 수정 : "... 호출 스택 및 모든 변수를 포함하지만 값이 없습니다"(또는 "모든 변수"만 삭제) 계속은 값을 유지하지 않고 호출 스택 만 포함합니다.
nalply

아니오, 연속은 "함수의 포인터"가 아닙니다. 가장 순진한 구현에서는 함수에 대한 포인터를 포함하고 환경은 로컬 변수를 보유합니다. call / cc와 같은 것을 사용하여 반환 값으로 캡처하지 않으면 반환되지 않습니다.
NalaGinrut

9

최신 버전의 Python에서는을 사용하여 Generators에 값을 보내서 generator.send()Python Generators를 효과적으로 코 루틴으로 만들 수 있습니다.

python Generator와 greenlet과 같은 다른 생성기의 주요 차이점은 python yield value에서는 호출자에게만 되돌릴 수 있다는 것입니다 . Greenlet에있는 동안 target.switch(value)특정 대상 코 루틴으로 이동하여 target계속 실행 되는 값을 산출 할 수 있습니다.


3
그러나 파이썬에서 모든 yield호출은 "Generator"라고하는 동일한 함수에 있어야합니다. 당신은 할 수 없습니다 yield파이썬의 호출 이유있는 하위 기능에서 반 코 루틴을 루아가있는 동안, 비대칭 코 루틴을 . (수율을 전파하기위한 제안이 있지만 그 물을 진흙탕으로 만 생각합니다.)
cdunn2001

7
@ cdunn2001 : (Winston의 주석) Python3.3에서는 하위 생성기에서 생성 할 수있는 "yield from"식을 도입했습니다.
Linus Caldwell
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.