Pergunta

Eu li em algum lugar onde Rich Hickey disse:

"Acho que as continuações podem ser legais em teoria, mas não na prática"

Não estou familiarizado com o clojure.
1. Clojure tem continuações?
2. Se não, você não precisa de continuação? Eu já vi muitos bons exemplos, especialmente de esse cara. Qual é a alternativa?
3. Se sim, existe uma documentação?

Foi útil?

Solução

Ao falar sobre continuações, você terá que distinguir entre dois tipos diferentes deles:

  • Continuações de primeira classe-o suporte à continuação que é profundamente integrado no idioma (esquema ou rubi). O Clojure não suporta continuações de primeira classe.

  • O estilo de passagem de continuação (CPS)-CPS é apenas um estilo de codificação e qualquer idioma que suporta funções anônimas permitirá esse estilo (que se aplica ao clojure também).

Exemplos:

-- Standard function
double :: Int -> Int
double x = 2 * x

-- CPS-function – We pass the continuation explicitly
doubleCPS :: Int -> (Int -> res) -> res
doubleCPS x cont = cont (2 * x)
; Call
print (double 2)

; Call CPS: Continue execution with specified anonymous function
double 2 (\res -> print res)

Ler continuação na Wikipedia.

Eu não acho que as continuações sejam necessárias para um bom idioma, mas especialmente continuações de primeira classe e CPs em idiomas funcionais como Haskell podem ser bastante úteis (Exemplo de retrocesso inteligente).

Outras dicas

Escrevi uma porta de clojure de Cl que adiciona continuações ao Lisp comum.

https://github.com/swannodette/delimc

A continuação é uma característica necessária em um idioma?

Não. Muitos idiomas não têm continuações.

Se não, você não precisa de continuação? Eu já vi muitos exemplos bons, especialmente desse cara. Qual é a alternativa?

Uma pilha de chamadas

Continuações abstratas

As continuações são uma noção abstrata usada para descrever a semântica do fluxo de controle. Nesse sentido, ambos existem e não existem (lembre -se, são abstratos) em qualquer idioma que ofereça operadores de controle (como qualquer linguagem completa de Turing deve), da mesma maneira que os números existem (como entidades abstratas) e Não existe (como entidades tangíveis).

As continuações descrevem efeitos de controle, como chamada/retorno da função, manuseio de exceção e até Gotos. Uma linguagem bem fundamentada, entre outras coisas, será projetada com abstrações que são construídas com continuação (por exemplo, exceções). (Ou seja, uma linguagem bem fundamentada consistirá em operadores de controle que foram projetados com continuações em mente. Controle a abstração, permitindo que os usuários construam suas próprias abstrações no topo.)

Continuações de primeira classe

Se a noção de uma continuação for reificado Como objeto de primeira classe em um idioma, temos uma ferramenta sobre a qual todos os tipos de efeitos de controle podem ser construídos. Por exemplo, se um idioma tiver continuações de primeira classe, mas não exceções, podemos construir exceções sobre as continuações.

Problemas com continuações de primeira classe

Embora as continuações de primeira classe sejam uma ferramenta poderosa e útil em muitos casos, também existem algumas desvantagens para expor-as em um idioma:

  • Diferentes abstrações construídas sobre as continuações podem resultar em comportamento inesperado / não intuitivo quando composto. Por exemplo, um finally O bloco pode ser ignorado se eu usar uma continuação para abortar um cálculo.
  • Se a continuação atual puder ser solicitada a qualquer momento, o tempo de execução do idioma deverá ser estruturado para que seja possível produzir alguma representação de estrutura de dados da continuação atual a qualquer momento. Isso coloca algum grau de carga no tempo de execução de um recurso que, para o bem ou para o mal, é frequentemente considerado "exótico". Se o idioma estiver hospedado (como Clojure estiver hospedado na JVM), essa representação deve ser capaz de se encaixar na estrutura fornecida pela plataforma de hospedagem. Também pode haver outros recursos que um idioma gostaria de manter (por exemplo, I interop) que restringem o espaço da solução. Questões como essas aumentam o potencial de uma "incompatibilidade de impedência" e podem complicar severamente o desenvolvimento de uma solução de desempenho.

Adicionando continuações de primeira classe a um idioma

Através da metaprogramação, é possível adicionar suporte para continuações de primeira classe a um idioma. Geralmente, essa abordagem envolve a transformação de código em estilo de passagem de continuação (CPS), no qual a continuação atual é passada como um argumento explícito para cada função.

Por exemplo, David Nolen's Delimc A biblioteca implementa continuações delimitadas de partes de um programa de clojure através de uma série de transformadas macro. Em uma linha semelhante, eu é autor Pulley.cps, que é um compilador de macro que transforma o código em CPS, juntamente com uma biblioteca de tempo de execução para suportar mais recursos de clojure (como manuseio de exceções), bem como interopear com o código de clojure nativo.

Um problema com essa abordagem é como você lida com o limite entre o código nativo (clojure) e o código transformado (CPS). Especificamente, como você não pode capturar a continuação do código nativo, você precisa não permitir (ou de alguma forma restringir) interopitar com a linguagem base ou colocar um ônus sobre o usuário de garantir que o contexto permitirá qualquer continuação que desejarem capturar para realmente ser capturado.

O Pulley.cps tende a este último, embora algumas tentativas tenham sido feitas para permitir que o usuário gerencie isso. Por exemplo, é possível proibir o código CPS para ligar para o código nativo. Além disso, é fornecido um mecanismo para fornecer versões de CPS das funções nativas existentes.

Em um idioma com um sistema de tipo suficientemente forte (como a Haskell), é possível usar o sistema de tipos para encapsular cálculos que podem usar operações de controle (isto é, continuações) do código funcionalmente puro.

Resumo

Agora temos as informações necessárias para responder diretamente às suas três perguntas:

  1. O Clojure não suporta continuações de primeira classe devido a considerações práticas.
  2. Todas as línguas são construídas sobre continuações no sentido teórico, mas poucos idiomas expõem continuações como objetos de primeira classe. No entanto, é possível adicionar continuações a qualquer idioma via, por exemplo, transformação em CPS.
  3. Confira a documentação para Delimc e/ou Pulley.cps.

Um uso comum das continuações está na implementação de estruturas de controle para: retornar de uma função, quebrar de um loop, manuseio de exceções etc. A maioria dos idiomas (como Java, C ++ etc) fornece esses recursos como parte do idioma principal. Alguns idiomas não (por exemplo: esquema). Em vez disso, esses idiomas expõem continuações como objetos de primeira classe e permitem que o programador defina novas estruturas de controle. Assim, o esquema deve ser encarado como um kit de ferramentas de linguagem de programação, não uma linguagem completa em si.

No Clojure, quase nunca precisamos usar continuações diretamente, porque quase todas as estruturas de controle são fornecidas pela combinação de idioma/VM. Ainda assim, as continuações de primeira classe podem ser uma ferramenta poderosa nas mãos do programador competente. Especialmente no esquema, as continuações são melhores que as contrapartes equivalentes em outros idiomas (como o par setjmp/longjmp em C). este O artigo tem mais detalhes sobre isso.

Aliás, será interessante saber como Rich Hickey justifica sua opinião sobre continuações. Algum link para isso?

Clojure (ou melhor, clojure.contrib.monads) tem uma Mônada de continuação; Aqui está um artigo que descreve seu uso e motivação.

Bem ... clojure's -> implementa o que você está depois ... mas com uma macro em vez

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