문제

그것들은 무엇이며 어떤 용도로 사용됩니까?

저는 CS 학위가 없으며 제 배경은 VB6 -> ASP -> ASP.NET/C#입니다.누구든지 명확하고 간결하게 설명할 수 있습니까?

도움이 되었습니까?

해결책

프로그램의 모든 단일 라인이 별도의 함수라고 상상해 보십시오.각각은 실행할 다음 행/함수를 매개변수로 받아들입니다.

이 모델을 사용하면 모든 라인에서 실행을 "일시 중지"하고 나중에 계속할 수 있습니다.또한 실행 스택을 임시로 올려 값을 검색하거나 현재 실행 상태를 데이터베이스에 저장하여 나중에 검색하는 등 창의적인 작업을 수행할 수도 있습니다.

다른 팁

당신은 아마도 당신이 생각했던 것보다 그것들을 더 잘 이해하고 있을 것입니다.

예외는 "상향 전용" 연속의 예입니다.이를 통해 스택 아래의 코드가 예외 처리기를 호출하여 문제를 나타낼 수 있습니다.

파이썬 예:

try:
    broken_function()
except SomeException:
    # jump to here
    pass

def broken_function():
    raise SomeException() # go back up the stack
    # stuff that won't be evaluated

생성기는 "하향 전용" 연속의 예입니다.예를 들어 새 값을 생성하기 위해 코드가 루프에 다시 들어갈 수 있습니다.

파이썬 예:

def sequence_generator(i=1):
    while True:
        yield i  # "return" this value, and come back here for the next
        i = i + 1

g = sequence_generator()
while True:
    print g.next()

두 경우 모두 언어에 구체적으로 추가해야 했지만 연속이 있는 언어에서는 프로그래머가 사용할 수 없는 이러한 항목을 만들 수 있습니다.

미리 말씀드리지만, 이 예는 간결하지도 않고 특별히 명확하지도 않습니다.이는 연속의 강력한 적용을 보여줍니다.VB/ASP/C# 프로그래머로서 시스템 스택의 개념이나 상태 저장에 익숙하지 않을 수 있으므로 이 답변의 목표는 설명이 아닌 데모입니다.

연속은 매우 다양하며 실행 상태를 저장하고 나중에 다시 시작하는 방법입니다.다음은 Scheme의 연속을 사용하는 협력적 멀티스레딩 환경의 작은 예입니다.

(여기에 정의되지 않은 전역 대기열에서 대기열 추가 및 대기열 제거 작업이 예상대로 작동한다고 가정합니다.)

(define (fork)
  (display "forking\n")
  (call-with-current-continuation
   (lambda (cc)
     (enqueue (lambda ()
                (cc #f)))
     (cc #t))))

(define (context-switch)
  (display "context switching\n")
  (call-with-current-continuation
   (lambda (cc)
     (enqueue
      (lambda ()
        (cc 'nothing)))
     ((dequeue)))))

(define (end-process)
  (display "ending process\n")
  (let ((proc (dequeue)))
    (if (eq? proc 'queue-empty)
        (display "all processes terminated\n")
        (proc))))

이는 함수가 사용할 수 있는 세 가지 동사(fork, context-switch 및 end-process)를 제공합니다.분기 작업은 스레드를 분기하고 한 인스턴스에서는 #t를 반환하고 다른 인스턴스에서는 #f를 반환합니다.컨텍스트 전환 작업은 스레드 간을 전환하고 프로세스 종료는 스레드를 종료합니다.

사용 예는 다음과 같습니다.

(define (test-cs)
  (display "entering test\n")
  (cond
    ((fork) (cond
              ((fork) (display "process 1\n")
                      (context-switch)
                      (display "process 1 again\n"))
              (else (display "process 2\n")
                    (end-process)
                    (display "you shouldn't see this (2)"))))
    (else (cond ((fork) (display "process 3\n")
                        (display "process 3 again\n")
                        (context-switch))
                (else (display "process 4\n")))))
  (context-switch)
  (display "ending process\n")
  (end-process)
  (display "process ended (should only see this once)\n"))

출력은 다음과 같아야합니다

entering test
forking
forking
process 1
context switching
forking
process 3
process 3 again
context switching
process 2
ending process
process 1 again
context switching
process 4
context switching
context switching
ending process
ending process
ending process
ending process
ending process
ending process
all processes terminated
process ended (should only see this once)

수업에서 포크와 스레딩을 공부한 사람들에게는 이와 유사한 예가 자주 제공됩니다.이 게시물의 목적은 연속을 사용하여 해당 상태(연속)를 수동으로 저장하고 복원하여 단일 스레드 내에서 유사한 결과를 얻을 수 있음을 보여주는 것입니다.

추신- On Lisp에서도 이와 비슷한 내용이 기억나는 것 같은데, 전문적인 코드를 보고 싶으시다면 책을 읽어보시면 좋을 것 같습니다.

연속을 생각하는 한 가지 방법은 프로세서 스택입니다."현재 연속 c 호출"을 수행하면 함수 "c"가 호출되고 "c"에 전달된 매개변수는 모든 자동 변수가 포함된 현재 스택입니다(또 다른 함수로 표시되는 경우 "k"라고 함). ").그 사이에 프로세서는 새로운 스택을 생성하기 시작합니다."k"를 호출하면 원래 스택에서 "서브루틴에서 복귀"(RTS) 명령이 실행되어 원래 "현재 연속 호출"(지금부터 "call-cc")의 컨텍스트로 다시 이동합니다. on) 프로그램이 이전과 같이 계속되도록 허용합니다."k"에 매개변수를 전달한 경우 이는 "call-cc"의 반환 값이 됩니다.

원래 스택의 관점에서 보면 "call-cc"는 일반 함수 호출처럼 보입니다."c"의 관점에서 볼 때 원래 스택은 결코 반환되지 않는 함수처럼 보입니다.

새장에 들어가서 잠그고 다른 모든 것(사자를 포함하여)이 새장 안에 있는 동안 자신은 새장 밖에 있다고 선언하여 새장에 있는 사자를 붙잡은 수학자에 대한 오래된 농담이 있습니다.연속은 새장과 약간 비슷하고, "c"는 수학자와 약간 비슷합니다.메인 프로그램은 "c"가 그 안에 있다고 생각하는 반면, "c"는 메인 프로그램이 "k" 안에 있다고 믿습니다.

연속을 사용하여 임의의 제어 흐름 구조를 만들 수 있습니다.예를 들어 스레딩 라이브러리를 만들 수 있습니다."yield"는 "call-cc"를 사용하여 현재 연속을 대기열에 넣은 다음 대기열의 선두에 있는 연속으로 점프합니다.세마포어에는 자체적으로 일시 중단된 연속 대기열이 있으며 스레드는 세마포어 대기열에서 꺼내어 기본 대기열에 배치하여 다시 예약됩니다.

기본적으로 연속은 함수의 실행을 중지한 다음 나중에 중단된 부분부터 다시 시작하는 기능입니다.C#에서는 Yield 키워드를 사용하여 이 작업을 수행할 수 있습니다.원한다면 더 자세히 설명할 수 있지만 간결한 설명을 원하셨습니다.;-)

나는 여전히 연속 작업에 "익숙"해지고 있지만, 연속 작업에 대해 내가 유용하다고 생각하는 한 가지 방법은 프로그램 카운터(PC) 개념을 추상화하는 것입니다.PC는 메모리에서 실행할 다음 명령을 "가리키지만" 물론 해당 명령(그리고 거의 모든 명령)은 묵시적이든 명시적이든 다음 명령뿐만 아니라 인터럽트를 처리해야 하는 모든 명령을 가리킵니다.(NOOP 명령어도 암시적으로 메모리의 다음 명령어로 점프합니다.그러나 인터럽트가 발생하면 일반적으로 메모리의 다른 명령으로 JUMP가 발생합니다.)

특정 지점에서 제어가 점프할 수 있는 메모리의 프로그램에서 잠재적으로 "살아 있는" 각 지점은 어떤 의미에서 활성 연속입니다.도달할 수 있는 다른 지점은 잠재적으로 활성 연속이지만 더 중요한 것은 현재 활성 연속 중 하나 이상에 도달한 결과로 잠재적으로 "계산"(아마도 동적으로)되는 연속입니다.

이는 모든 보류 중인 실행 스레드가 명시적으로 정적 코드의 연속으로 표시되는 연속에 대한 전통적인 소개에서는 약간 벗어난 것 같습니다.그러나 범용 컴퓨터에서 PC는 해당 명령어 시퀀스의 일부를 나타내는 메모리의 내용을 잠재적으로 변경할 수 있는 명령어 시퀀스를 가리키므로 본질적으로 새로운(또는 원하는 경우 수정된) 생성이 가능하다는 사실을 고려합니다. ) 즉석에서 연속, 해당 생성/수정 이전의 연속 활성화로 인해 실제로 존재하지 않는 연속입니다.

따라서 연속은 PC의 상위 수준 모델로 볼 수 있으며, 이것이 개념적으로 일반적인 프로시저 호출/반환을 포함하는 이유입니다(고대 철이 GOTO라고도 불리는 저수준 JUMP, 명령과 기록을 통해 프로시저 호출/반환을 수행한 것처럼). 호출 중인 PC 및 반환 시 복원)뿐만 아니라 예외, 스레드, 코루틴 등도 포함됩니다.

따라서 PC가 "미래"에 일어날 계산을 가리키는 것처럼 연속은 동일한 작업을 수행하지만 더 높고 더 추상적인 수준에서 수행됩니다.PC는 암묵적으로 메모리와 모든 메모리 위치를 참조하고 모든 값에 "바인딩된" 레지스터를 참조하며, 연속은 언어에 적합한 추상화를 통해 미래를 나타냅니다.

물론 일반적으로 컴퓨터당 하나의 PC(코어 프로세서)만 있을 수 있지만 위에서 언급한 것처럼 실제로는 "활성" PC 같은 엔터티가 많이 있습니다.인터럽트 벡터에는 한 묶음이 포함되고, 스택에는 더 많은 묶음이 포함되며, 특정 레지스터에는 일부가 포함될 수 있습니다.해당 값이 하드웨어 PC에 로드될 때 "활성화"되지만 연속은 개념의 추상화이며 PC 또는 정확한 등가물이 아닙니다. "마스터" 연속이라는 고유한 개념은 없지만 종종 이러한 용어로 생각하고 코딩합니다. 일을 상당히 단순하게 유지하기 위해).

본질적으로 연속은 "호출될 때 다음에 수행할 작업"을 표현한 것이며, 따라서 다음과 같은 일류 객체가 될 수 있습니다(일부 언어 및 연속 전달 스타일 프로그램에서는 종종 그렇습니다). 대부분의 다른 데이터 유형과 마찬가지로 인스턴스화되고 전달되고 폐기되며 기존 컴퓨터가 메모리 위치를 처리하는 방식과 유사합니다. 대비 PC - 일반 정수와 거의 상호 교환 가능합니다.

C#에서는 두 개의 연속에 액세스할 수 있습니다.하나, 다음을 통해 액세스됨 return, 메소드가 호출된 위치부터 계속되도록 합니다.다른 하나는 다음을 통해 액세스됩니다. throw, 가장 가까운 일치에서 메서드를 계속하도록 합니다. catch.

일부 언어에서는 이러한 명령문을 일급 값으로 처리할 수 있으므로 이를 할당하고 변수로 전달할 수 있습니다.이것이 의미하는 바는 다음과 같은 가치를 숨길 수 있다는 것입니다. return 또는 throw 나중에 시간 나면 전화해 정말 반환하거나 던질 준비가되었습니다.

Continuation callback = return;
callMeLater(callback);

이는 다양한 상황에서 유용할 수 있습니다.한 가지 예는 위와 같으며, 수행 중인 작업을 일시 중지하고 나중에 어떤 일(예: 웹 요청을 받는 등)이 발생하면 다시 시작하려는 경우입니다.

저는 제가 작업하고 있는 몇 가지 프로젝트에서 그것들을 사용하고 있습니다.하나는 네트워크를 통해 IO를 기다리는 동안 프로그램을 일시 중지했다가 나중에 다시 시작할 수 있도록 사용하는 것입니다.다른 하나에서는 사용자가 값으로 연속에 액세스하여 쓸 수 있도록 하는 프로그래밍 언어를 작성하고 있습니다. return 그리고 throw 자체적으로 또는 다른 제어 흐름을 위해 while 루프 - 내가 대신 할 필요가 없습니다.

스레드를 생각해 보세요.스레드를 실행할 수 있으며 해당 스레드의 계산 결과를 얻을 수 있습니다.연속은 복사할 수 있는 스레드이므로 동일한 계산을 두 번 실행할 수 있습니다.

연속은 웹 요청의 일시 중지/재개 특성을 훌륭하게 반영하기 때문에 웹 프로그래밍에 대한 새로운 관심을 불러일으켰습니다.서버는 사용자 세션을 나타내는 연속을 구성하고 사용자가 세션을 계속하는 경우 재개할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top