Pergunta

Isto está relacionado com O que é chamada / cc? , mas eu não queria sequestrar esta pergunta para os meus próprios fins, e alguns de seus argumentos como a analogia com setjmp / longjmp evade mim.

Eu acho que tenho uma idéia suficiente sobre o que uma continuação é, eu penso nisso como um instantâneo da pilha de chamadas atual. Eu não quero entrar na discussão por que isso pode ser interessante ou o que você pode fazer com continuações. A minha pergunta é, mais especificamente, por que eu tenho para oferecer um argumento função para chamada / cc? Por que não chama / cc basta retornar a continuação atual, para que eu pudesse fazer o que eu quiser com ele (armazená-lo, chamá-lo, o nome dele)? Em um link a partir desta outra questão ( http: // comunidade .schemewiki.org /? call-com-presente-continuation-para-C-programadores ), fala sobre "Essencialmente é apenas uma maneira limpa para obter a continuação para você e manter fora do caminho de saltos subseqüentes volta para o ponto salvo. ", mas não estou conseguindo. Parece desnecessariamente complicado.

Foi útil?

Solução 4

Contra netiqueta tão comum que eu estou respondendo a minha própria pergunta, mas mais como o editor do que o provedor da resposta.

Depois de um tempo eu comecei a uma pergunta semelhante sobre a LTU . Afinal, estes são os caras que a linguagem Ponder projetar todo o dia, não são eles, e um dos respostas finalmente chutou comigo. Agora as coisas mencionadas aqui, por exemplo, por Eli ou na pergunta original, faz muito mais sentido para mim. É tudo sobre o que é incluído na continuação, e onde os conjuntos de continuação aplicada na.

Uma das cartazes na LTU escreveu:

"Você pode ver exatamente como chamada / cc lhe permite 'manter fora do caminho.' Com los ou obter / cc que você precisa fazer algum tipo de teste para determinar se você tem um back-jump ou apenas a inicial chamada. Basicamente, chamada / cc mantém o uso da continuação para fora da continuidade, enquanto que com get / cc ou em, a continuação contém o seu uso e assim (geralmente) você precisa adicionar um teste para o início da continuação (ou seja, imediatamente após get / cc / em) para separar o "usando as peças de continuação" do "resto da continuação" partes ".

Isso levou-o para casa para mim.

Obrigado caras de qualquer maneira!

Outras dicas

Se você usar uma construção como shows de Jay, então você pode pegar a continuação, mas de certa forma, o valor que é agarrado já está estragado porque você já dentro que a continuação está. Em contraste, call/cc pode ser usado para agarrar a continuação que é ainda pendente fora da expressão atual. Por exemplo, um dos usos mais simples de continuações é implementar uma espécie de abort:

(call/cc (lambda (abort)
           (+ 1 2 (abort 9))))

Você não pode fazer isso com a operação que você descreve. Se você tentar isso:

(define (get-cc) (call/cc values))
(let ([abort (get-cc)]) (+ 1 2 (abort 9)))

então você obtém um erro sobre a aplicação 9 como um procedimento. Isso acontece porque abort salta de volta para a let com o novo valor de 9 - o que significa que você está fazendo agora uma segunda rodada da mesma expressão disso, exceto que agora abort é obrigado a 9 ...

Duas notas adicionais relacionados a:

  1. Para uma boa uma introdução prática para continuações, consulte PLAI .
  2. call/cc é um pouco complexo na medida em que leva em uma função - um conceitualmente mais fácil construir uso é let/cc que você pode encontrar em algumas implementações, como PLT Scheme. O exemplo acima torna-se (let/cc abort (+ 1 2 (abort 9))).

Isso seria menos versátil. Se você quiser que o comportamento, você pode apenas fazer:

(call/cc (lambda (x) x))

Você poderia dar uma olhada no exemplo usos de continuações em "Darrell Ferguson e Dwight Deugo. 'Call com padrões de continuação atuais'. 8ª Conferência de Linguagens padrão de Programas. Setembro de 2001." ( http://library.readscheme.org/page6.html ) e tentar reescrevê-los usando a / cc-retorno de chamada, como acima definido.

Eu sugiro começar por perguntar-se: o que significa ser uma continuação de primeira classe

A continuação de uma expressão consiste essencialmente de duas peças de dados: primeira, o dispositivo de fecho (isto é, ambiente) de que a expressão; e, segundo, uma representação do que deve ser feito com o resultado da expressão. Uma linguagem com continuações de primeira classe, então, é aquele que tem estruturas de dados encapsulando essas partes, e que trata essas estruturas de dados da mesma forma que faria com qualquer outro.

Chamada / cc é uma forma particularmente elegante para realizar essa idéia: a continuação atual é empacotado como um procedimento que encapsula o-que-é-a-ser feito-com-o-expressão como o que o procedimento não quando aplicado a a expressão; para representar a continuação desta forma significa simplesmente que o encerramento deste processo contém o ambiente no local foi invocado.

Você poderia imaginar perceber a ideia de continuações de primeira classe em outras maneiras. Eles não seria chamada / cc, e é difícil para mim imaginar como tal representação poderia ser mais simples.

Em uma nota de despedida, considere a implementação de let / cc que Eli mencionado, que eu prefiro chamar bind / cc:

(define-syntax bind/cc
    (syntax-rules ()
        ((bind/cc var . body)
             (call/cc (lambda (var) . body)))))

E como um exercício, como você implementar chamada / cc baseado em bind / cc?

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