Pergunta

O que são e para que servem elas?

Eu não tenho um CS grau e meu plano de fundo é VB6 -> ASP -> ASP.NET/C#.Alguém pode explicar de uma forma clara e concisa?

Foi útil?

Solução

Imagine se cada linha no seu programa era uma função separada.Cada um aceita, como um parâmetro, a próxima linha/função para executar.

Usando este modelo, você pode "pausar" a execução em qualquer linha e continuar-lo mais tarde.Você também pode fazer inventiva coisas como se temporariamente hop até a pilha de execução para obter um valor, ou salvar o atual estado de execução para um banco de dados para recuperar mais tarde.

Outras dicas

Provavelmente você entender melhor do que você acha que você fez.

As exceções são um exemplo de "para cima" apenas continuações.Eles permitem o código no fundo da pilha de chamada para um manipulador de exceção para indicar um problema.

Python exemplo:

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

Geradores são exemplos de "para baixo" só de continuações.Eles permitem que o código para reintroduzir um loop, por exemplo, para criar novos valores.

Python exemplo:

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()

Em ambos os casos, estas deveriam ser adicionados à linguagem, especificamente, enquanto que em um idioma com continuações, o programador pode criar essas coisas onde elas não estão disponíveis.

Um heads-up, este exemplo não é concisa, nem excepcionalmente claro.Esta é uma demonstração de um poderoso aplicativo de continuações.Como VB, ASP/C# programador, você pode não estar familiarizado com o conceito de um sistema de pilha ou de poupança de estado, portanto, o objetivo desta resposta é uma demonstração e não uma explicação.

Continuações são extremamente versáteis e são uma forma de salvar o estado de execução e retomá-lo mais tarde.Aqui está um pequeno exemplo de uma cooperativa ambiente multithread usando continuações em Regime de:

(Suponha que as operações enqueue e dequeue funcionar como esperado em uma fila global não definido aqui)

(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))))

Isso fornece três verbos que uma função pode utilizar - garfo, contexto-switch, e no final do processo.O garfo operação de garfos de linha e retorna #t em uma instância e #f em outro.O contexto de operação do switch comuta entre threads, e no final do processo termina um thread.

Aqui está um exemplo de seu uso:

(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"))

A saída deve ser

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)

Aqueles que estudaram a bifurcação e rosqueamento em uma classe são, muitas vezes, exemplos semelhantes a este.O objetivo deste post é demonstrar que, com a continuação você pode obter resultados semelhantes dentro de um único segmento salvando e restaurando o seu estado, a sua continuação - manualmente.

P. S.- Eu acho que eu lembro de algo semelhante a isto no Lisp, por isso, se você gostaria de ver profissionais de código, você deve verificar o livro.

Uma maneira de pensar de uma continuação é como um processador de pilha.Quando você "call-with-current-continuation c" chama a função "c", e o parâmetro passado para o "c" é a sua pilha atual com todas as suas variáveis automáticas sobre ele (representado como ainda outra função, chamada de "k").Enquanto isso, o processador começa a criar uma nova pilha.Quando você chama de "k", ele executa um "retorno da sub-rotina" (RTS) de instrução sobre a pilha original, pulando de volta para o contexto original de "call-with-current-continuation" ("call-cc" a partir de agora) e permitindo que seu programa continue como antes.Se você passou um parâmetro "k", então torna-se o valor de retorno o "call-cc".

Do ponto de vista de sua pilha original, o "call-cc" parece-se com uma chamada de função normal.Do ponto de vista de "c", sua pilha original parece uma função que não retorna jamais.

Há uma velha piada sobre um matemático que capturou a imagem de um leão em uma gaiola por subir na gaiola, fecho-lo, e declarando-se fora da gaiola, enquanto tudo o mais (incluindo o leão) foi dentro dela.Continuações são um pouco como a gaiola, e "c" é um pouco como o matemático.Seu principal programa considera que "c" é de dentro dela, enquanto "c", acredita que o seu principal do programa está dentro de "k".

Você pode criar arbitrário de fluxo de controle de estruturas usando continuações.Por exemplo, você pode criar uma thread library."rendimento" usa "chamar-cc" para colocar a continuação em uma fila e, em seguida, salta para o um na cabeça da fila.Um semáforo também tem sua própria fila de suspenso continuações, e uma thread é remarcada por tirar o semáforo fila e colocá-lo na fila principal.

Basicamente, uma continuação é a capacidade de uma função para parar a execução e, em seguida, pegar de volta de onde parou em um ponto posterior no tempo.Em C#, você pode fazer isso usando o rendimento de palavras-chave.Eu posso entrar em mais detalhes, se você deseja, mas você queria uma explicação concisa.;-)

Eu ainda estou começando "usado" para a continuação, mas uma maneira de pensar sobre eles que eu acho úteis é como abstrações do Contador de Programa (PC) conceito.Um PC "pontos" para a próxima instrução a executar na memória, mas é claro que a instrução (e praticamente toda a instrução) pontos, implicitamente ou explicitamente, a instrução que se segue, bem como a quaisquer instruções que devem interrupções de serviço.(Mesmo que seja uma instrução de NOOP, implicitamente, faz um SALTO para a próxima instrução na memória.Mas se ocorre uma interrupção, que geralmente envolvem um SALTO para alguma outra instrução na memória.)

Cada potencialmente "ao vivo" de ponto em um programa na memória para o qual o controle pode saltar a qualquer dado ponto é que, num sentido, um ativo de continuação.Outros pontos que podem ser atingidos são potencialmente ativos, continuações, mas, mais para o momento, eles são continuações que são potencialmente "calculado" (dinamicamente, talvez) como resultado de alcançar um ou mais dos ativos atualmente continuações.

Isto parece um pouco fora de lugar em tradicionais apresentações para continuações, em que todos os pendentes threads de execução são explicitamente representados como continuações em estática de código;mas leva em conta o fato de que, em computadores de uso geral, o PC aponta para uma sequência de instruções que podem potencialmente alterar o conteúdo da memória representa uma parte do que a sequência de instruções, portanto, essencialmente, a criação de um novo (ou modificado, se quiser) continuação na mosca, que, realmente, não existe como das ativações de continuações anteriores de que a criação/modificação.

Modo de continuação pode ser visto como um alto nível de modelo para o PC, que é por isso que, conceptualmente, inclui procedimento ordinário chamada/retorno (assim como o antigo ferro de engomar fez o procedimento de chamada/retorno via de baixo nível SALTO, aka GOTO, instruções plus gravação do PC de serviço e restauração de devolução) bem como de exceções, threads, co-rotinas, etc.

Assim como o PC aponta para cálculos acontecer no "futuro", uma continuação não é a mesma coisa, mas em uma maior, mais abstratas nível.O PC refere-se implicitamente a memória, além de todos os locais de memória e registradores "dependente" de valores que, enquanto uma continuação representa o futuro através do idioma apropriado abstrações.

É claro que, enquanto não pode, normalmente, ser apenas um PC por computador (processador de núcleo), há, de fato, muitos "ativo" PC-ish entidades, como aludido acima.O vetor de interrupção contém um monte, pilha um grupo de mais, alguns registos podem conter algumas, etc.Eles são "ativadas" quando seus valores são carregados para o hardware do PC, mas continuações são a abstração do conceito, não o pc ou os seus preciso equivalente (não é inerente o conceito de um "mestre" de continuação, embora muitas vezes pensamos e código nesses termos para manter as coisas bem simples).

Em essência, uma continuação é uma representação de "o que fazer quando invocado", e, como tal, pode ser (e, em alguns idiomas, e na continuação da passagem estilo de programas, muitas vezes é) uma primeira classe de objeto é instanciado, passado em torno, e descartado como qualquer outro tipo de dados, e muito, como um computador clássico trata de localizações de memória vis-a-vis PC-como quase intercambiáveis com números inteiros normais.

Em C#, você tem acesso a duas continuações.Um, acessada através de return, permite que um método de continuar a partir de onde foi chamado.O outro, acessada através de throw, permite que um método de continuar a correspondência mais próxima catch.

Algumas linguagens permitem tratar estas declarações como valores de primeira classe, para que você possa atribuí-los e passá-los em variáveis.O que isto significa é que você pode sair com o valor de return ou de throw e chamá-los mais tarde, quando você está realmente pronto para retornar ou jogar.

Continuation callback = return;
callMeLater(callback);

Isto pode ser útil em muitas situações.Um exemplo é como a de cima, onde você deseja interromper o trabalho que você está fazendo e retomá-lo mais tarde, quando algo acontece (como a obtenção de uma solicitação da web, ou algo assim).

Eu estou usando-os em um par de projetos em que estou trabalhando.Em um, eu estou usando-os para que eu possa suspender o programa, enquanto eu estou esperando por e / s através da rede e, em seguida, retomá-lo mais tarde.No outro, eu estou escrevendo uma linguagem de programação onde eu dar ao usuário acesso a continuação-como-valores para que eles possam escrever return e throw para si ou para qualquer outro fluxo de controle, como while ciclos - sem eu precisar fazer isso por eles.

Acho que de threads.Uma thread pode ser executado, e você pode obter o resultado de seu cálculo.Uma continuação é um thread que você pode copiar, de modo que você pode executar a mesma computação duas vezes.

Continuação de ter tido um interesse renovado com programação web porque eles bem o espelho pausar/reiniciar a personagem de solicitações da web.Um servidor pode construir uma continaution representando uma sessão aos utilizadores e continuar se e quando o usuário continuar a sessão.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top