Uso de Cálculo de Processo e Teoria PL para desenvolvimento de linguagem de programação moderna


10

Há algum tempo, estou muito interessado em teoria da linguagem de programação e cálculo de processos e comecei a estudá-los. Para ser honesto, é algo que eu não me importaria de seguir para uma carreira. Acho a teoria incrivelmente fascinante. Uma pergunta constante em que continuo me deparando é se a Teoria do PL ou o Cálculo do Processo têm alguma importância no desenvolvimento da linguagem de programação moderna. Eu vejo tantas variantes no cálculo Pi por aí e há muita pesquisa ativa, mas elas serão necessárias ou terão aplicações importantes? A razão pela qual pergunto é porque eu amo desenvolver linguagens de programação e o verdadeiro objetivo final seria usar a teoria para realmente construir um PL. Para as coisas que escrevi, realmente não houve nenhuma correlação com a teoria.

Respostas:


9

Minha resposta é realmente apenas uma elaboração de Gilles, que eu não havia lido antes de escrever a minha. Talvez seja útil.

Deixe-me começar minha tentativa de responder sua pergunta com uma distinção entre duas dimensões do trabalho das linguagens de programação que se relacionam de maneira bastante diferente à teoria da linguagem de programação em geral e ao cálculo do processo em particular.

  • Pesquisa pura.

  • Pesquisa e desenvolvimento focados no produto.

O último ocorre tipicamente na indústria, com o objetivo de fornecer linguagens de programação como um produto. As equipes que desenvolvem Java na Oracle e C # na Microsoft são exemplos. Por outro lado, a pesquisa pura não está ligada a produtos. Seu objetivo é entender as linguagens de programação como objetos de interesse intrínseco e explorar as estruturas matemáticas subjacentes a todas as linguagens de programação.

Devido a objetivos divergentes, diferentes aspectos da teoria da linguagem de programação são relevantes em pesquisa pura e em pesquisa e desenvolvimento focados em produtos. A imagem abaixo pode dar uma indicação do que é importante onde.

insira a descrição da imagem aqui

Pode-se perguntar neste ponto por que as duas dimensões são tão aparentemente diferentes e como elas se relacionam.

O insight principal é que a pesquisa e o desenvolvimento da linguagem de programação têm múltiplas dimensões: técnica, social e econômica. Quase por definição, a indústria está interessada no retorno econômico das linguagens de programação. Microsoft e colaboradores não desenvolvem linguagens a partir da bondade de seus corações, mas porque acreditam que as linguagens de programação lhes dão uma vantagem econômica. E eles investigaram profundamente por que algumas linguagens de programação são bem-sucedidas e outras, aparentemente semelhantes ou com recursos mais avançados, não. E eles descobriram que não há uma única razão. As linguagens de programação e seus ambientes são complexos, e também as razões para a adoção ou ignoração de qualquer linguagem específica. Mas o maior fator para o sucesso de uma linguagem de programação é o apego preferencial de programadores a linguagens já amplamente utilizadas: quanto mais pessoas usam uma linguagem, mais bibliotecas, ferramentas, material didático estão disponíveis e mais produtivo é o programador. pode estar usando esse idioma. Isso também é chamado de efeito de rede. Outro motivo é o alto custo da troca de linguagens para indivíduos e organização: dominar a linguagem, especialmente para um programador não tão experiente, e quando a distância semântica para linguagens familiares é grande, é um esforço sério e demorado. Diante desses fatos, pode-se perguntar por que os novos idiomas são atraídos? Por que as empresas desenvolvem novos idiomas? Por que não ficamos apenas com Java ou Cobol? Penso que existem várias razões principais para o soro de leite que uma língua tenha sucesso,

  • Um novo domínio de programação é aberto e não há titulares a serem substituídos. O exemplo principal é a web com seu aumento concomitante de Javascript.

  • Visibilidade de linguagem. Com isso, quero dizer o alto preço da mudança de idioma. Mas, às vezes, os programadores se mudam para campos diferentes, levando consigo uma linguagem de programação e obtendo sucesso com a linguagem antiga no novo campo.

  • Uma linguagem é promovida por uma grande empresa com poder de fogo financeiro sério. Esse apoio reduz o risco de adoção, porque os adotantes iniciais podem ter certeza razoável de que o idioma ainda será suportado em alguns anos. Um bom exemplo disso é o C #.

  • Um idioma pode vir com ferramentas atraentes e ecossistema. Aqui também C # e seu ecossistema .Net e Visual Studio podem ser mencionados como exemplo.

  • Os idiomas antigos adquirem novos recursos. O Java vem à mente, o qual, a cada iteração, capta mais boas idéias da tradição de programação funcional.

  • Finalmente, um novo idioma pode ter vantagens técnicas intrínsecas, por exemplo, ser mais expressivo, ter uma sintaxe melhor, sistemas de digitação que detectam mais erros etc.

Dado esse pano de fundo, não deve surpreender que exista uma desconexão entre pura pesquisa em linguagem de programação e desenvolvimento comercial de linguagem de programação. Embora ambos tenham como objetivo tornar a construção e a evolução do software mais eficientes, especialmente para software em larga escala, o trabalho da linguagem de programação industrial deve estar mais interessado em facilitar a adoção rápida para atingir uma massa crítica e obter o efeito de rede. Isso leva a um foco de pesquisa em coisas que os programadores que trabalham se preocupam. E isso tende a incluir coisas como disponibilidade de biblioteca, velocidade do compilador, qualidade do código compilado, portabilidade e assim por diante. O cálculo de processo como o praticamos hoje é de pouca utilidade para programadores que trabalham em projetos convencionais (embora eu acredite que isso mudará no futuro).

λπβ-redução para programação funcional, resolução / unificação para programação lógica, passagem de nome para computação simultânea). Para entender se um idioma como o Scala pode ter uma inferência de tipo completa viável, não precisamos nos preocupar com a JVM. De fato, pensar na JVM prejudicará uma melhor compreensão da inferência de tipo. É por isso que a abstração da computação em pequenos cálculos de núcleo é vital e poderosa.

Assim, você pode pensar na pesquisa em linguagem de programação como uma enorme caixa de areia onde as pessoas brincam com brinquedos e, se encontram algo interessante ao brincar com um brinquedo específico e investigam o brinquedo minuciosamente, esse brinquedo interessante inicia sua longa marcha em direção à aceitação industrial convencional . Digo uma longa marcha porque os recursos da linguagem inventados pela primeira vez pelo pesquisador da linguagem de programação tendem a levar décadas para serem amplamente aceitos. Por exemplo, a coleta de lixo foi concebida na década de 1950 e tornou-se amplamente disponível com Java na década de 1990. A correspondência de padrões remonta a 1970 e é amplamente usada apenas desde Scala.

O cálculo de processo é um brinquedo especialmente interessante. Mas é novo demais para ser investigado minuciosamente. Isso levará mais uma década de pesquisa pura. O que está acontecendo atualmente na pesquisa de teoria de processos é pegar a maior história de sucesso da pesquisa em linguagem de programação, a teoria de tipos (seqüenciais) e desenvolver a teoria de tipos para simultaneidade de passagem de mensagem. Sistemas de digitação de expressividade moderada para programação seqüencial, dizem Hindley-Milner, agora são bem compreendidos, onipresentes e aceitos pelos programadores que trabalham. Gostaríamos de ter tipos moderadamente expressivos para programação simultânea. Pesquisas sobre isso começaram na década de 1980 por pioneiros como Milner, Sangiorgi, Turner, Kobayashi, Honda e outros, freqüentemente baseados, explícita ou implicitamente, na idéia de linearidade que vem da lógica linear. Os últimos anos viram um grande aumento de atividade e espero que essa trajetória ascendente continue no futuro próximo. Também espero que este trabalho comece a vazar para P&D focada em produtos, em parte pelo motivo pragmático de que jovens pesquisadores treinados em cálculo de processos trabalharão em laboratórios industriais de P&D, mas também devido à evolução da CPU e da arquitetura de computadores. de formas seqüenciais de computação.

Em resumo, não me preocuparia que você não ache a teoria da linguagem de programação de ponta, como o cálculo de processo, útil em seu próprio trabalho de construção de linguagens. Isso é simplesmente porque a teoria de ponta não trata das preocupações das linguagens de programação atuais. É sobre idiomas futuros. Vai demorar um pouco para o 'mundo real' se atualizar. O conhecimento que você usa para criar linguagens para hoje é a teoria da linguagem de programação do passado. Encorajo-vos a aprender mais sobre cálculo de processos, porque é uma das áreas mais interessantes de toda a ciência da computação teórica.


11
Uau! Quanto tempo levou para fazer esse diagrama, e posso usá-lo no futuro?
Cody

11
@cody Tomou alguns segundos com o OmniGraffle e sinta-se à vontade para usá-lo.
Martin Berger

8

A ciência do design da linguagem de programação está em sua infância. A teoria (o estudo do significado de programas e a expressividade de uma linguagem) e o empirismo (o que os programadores gerenciam ou não conseguem fazer) fornecem muitos argumentos qualitativos para avaliar de uma maneira ou de outra ao projetar uma linguagem. Mas raramente temos motivos quantitativos para decidir.

Há um atraso entre o tempo em que uma teoria se estabiliza o suficiente para que uma inovação seja utilizável em uma linguagem de programação prática e o tempo em que essa inovação começa a aparecer em linguagens "mainstream". Por exemplo, pode-se dizer que o gerenciamento automático de memória com coleta de lixo amadureceu para uso industrial em meados da década de 1960, mas só alcançou o mainstream com Java em 1995. O polimorfismo paramétrico foi bem compreendido no final da década de 1970 e o tornou em Java em meados dos anos 200. Na escala da carreira de um pesquisador, 30 anos é muito tempo.

A adoção industrial de uma língua em larga escala é uma questão para os sociólogos estudarem, e essa ciência está ainda mais engatinhada. As considerações de mercado são um fator importante - se a Sun, a Microsoft ou a Apple adotam um idioma, isso tem muito mais impacto do que qualquer número de documentos POPL e PLDI. Mesmo para um programador que tem uma escolha, a disponibilidade da biblioteca geralmente é muito mais importante que o design da linguagem. O que não quer dizer que o design da linguagem não seja importante: ter uma linguagem bem projetada é um alívio! Geralmente não é o fator decisivo.

Os cálculos do processo ainda estão no estágio em que a teoria não se estabilizou. Acreditamos que entendemos cálculos seqüenciais - todos os modelos de coisas que gostamos de chamar de cálculo sequencial são equivalentes (essa é a tese de Church-Turing). Isso não se aplica à simultaneidade: cálculos de processos diferentes tendem a ter diferenças sutis na expressividade.

Os cálculos de processo têm implicações práticas. Muitos cálculos lá fora são distribuídos - eles envolvem clientes conversando com servidores, servidores conversando com outros servidores, etc. Mesmo os cálculos locais são frequentemente multithread para aproveitar o paralelismo em vários processadores e reagir à concorrência ambiental (comunicação com programas independentes e com o usuário).

São necessários avanços de pesquisa para criar um software melhor? Afinal, existe uma indústria de bilhões de dólares por aí que não consegue distinguir o cálculo pi de uma torta no céu. Por outro lado, esse setor gasta bilhões de dólares consertando bugs.

"Eles serão necessários" nunca é uma questão que vale a pena na pesquisa. É impossível prever com antecedência o que terá consequências a longo prazo. Eu diria ainda mais que é uma suposição segura de que qualquer pesquisa terá consequências um dia - simplesmente não sabemos na época se esse dia chegará no próximo ano ou no próximo milênio.


3

Eu vejo tantas variantes no cálculo Pi por aí e há muita pesquisa ativa, mas elas serão necessárias ou terão aplicações importantes?

A razão pela qual pergunto é porque eu amo desenvolver linguagens de programação e o verdadeiro objetivo final seria usar a teoria para realmente construir um PL. Para as coisas que escrevi, realmente não houve nenhuma correlação com a teoria.

Esta é uma pergunta complicada! Vou lhe dizer minha opinião pessoal e enfatizo que essa é minha opinião .

Eu não acho que pi-calculus seja diretamente adequado como uma notação para programação simultânea. No entanto, acho que você definitivamente deveria estudá-lo antes de criar uma linguagem de programação simultânea. A razão é que o cálculo pi fornece um nível baixo - mas, o que é mais importante, de composição! --- conta de simultaneidade. Como resultado, ele pode expressar tudo o que você deseja, mas nem sempre de forma conveniente.

Explicar esse comentário requer pensar um pouco sobre os tipos. Primeiro, linguagens de programação úteis geralmente precisam de algum tipo de disciplina de tipo para criar abstrações. Em particular, você precisa de algum tipo de tipo de função para fazer uso de abstrações processuais ao criar software.

Agora, a disciplina de tipo natural do cálculo pi é uma variante da lógica linear clássica. Veja, por exemplo, o artigo de Abramsky, Process Realizability , que mostra como você interpreta programas simultâneos simples como provas de proposições da lógica linear. (A literatura contém muito trabalho sobre tipos de sessão para digitar programas de cálculo pi, mas tipos de sessão e tipos lineares estão intimamente relacionados.)

ABAB

Isso é bom com a teoria do tipo POV, mas é estranho na programação. O motivo é que os programadores acabam gerenciando não apenas suas chamadas de função, mas também a pilha de chamadas. (De fato, as codificações do cálculo lambda no cálculo pi geralmente se parecem com as transformações do CPS.) Agora, a digitação garante que eles nunca estragarão tudo isso, mas, no entanto, há muita contabilidade imposta ao programador.

Este não é um problema exclusivo da teoria da concorrência - o mu-calculus fornece uma boa explicação teórica de operadores de controle seqüencial como call / cc, mas com o preço de tornar a pilha explícita, o que a torna uma linguagem de programação estranha.

Portanto, ao projetar uma linguagem de programação simultânea, minha opinião é que você deve projetar sua linguagem com abstrações de nível superior ao cálculo pi, mas certifique-se de que ela seja traduzida corretamente em um cálculo de processo digitado. (Um bom exemplo recente disso são os processos, funções e sessões de ordem superior de Tonhino, Caires e Pfenning : uma integração monádica .)


Em que sentido você precisa gerenciar a pilha de chamadas no -calculus? Isso acontece automaticamente na codificação de em Milner e também na nova codificação de Van Bakel / Vigliotti. As funções são uma forma perfeitamente fina de açúcar sintático no cálculo . πλππ
Martin Berger

Além disso, o -calculus é uma conta realmente incômoda para os operadores de controle seqüencial como call / cc. Esses operadores são muito mais fáceis e naturalmente expressos no caluclus, porque saltar é claramente uma forma de passagem de mensagens. -calculus não possui uma noção natural de nome para a qual você pode pular, portanto, você deve codificá-lo como aplicativo de função ou adicionar itens adicionais. λμπλ
Martin Berger

Uma maneira proveitosa de pensar em funções é que elas são interações cliente-servidor, em que o canal de retorno é afinado e o canal do servidor é replicado. Isso pode ser digitado facilmente. Os tipos de sessão não capturam isso completamente, pois são um pouco fracos nas restrições de interação que impõem.
Martin Berger

Tudo isso dito, é claro que não se deseja programar em raw -calculus mais do que em raw -calculus. Ambos formalismos são simplificações que nos permitem focar em alguns recursos da computação, excluindo outros. πλ
Martin Berger

@ MartinBerger: Eu esperava convencê-lo a responder! Quero dizer que, se você quisesse programar em raw , e também quisesse usar funções, acabaria escrevendo termos que estão na imagem da tradução de Milner e, portanto, teria que "gerenciar a pilha" no sentido de que você estaria gerenciando essencialmente continuações e substituições explícitas. (Como um aparte, eu não sabia sobre a van papel Bakel / Vigliotti - muito obrigado!)π
Neel Krishnaswami

1

Você diz que "o verdadeiro objetivo final seria usar a teoria para realmente construir um PL". Então, você presumivelmente admite que existem outros objetivos?

Do meu ponto de vista, o objetivo número 1 da teoria é fornecer entendimento, o que pode estar no raciocínio sobre linguagens de programação existentes, bem como sobre os programas escritos nelas. Nas horas vagas, mantenho um grande software, um cliente de e-mail, escrito há muito tempo no Lisp. Toda a teoria do PL que eu conheço, como lógica de Hoare, lógica de separação, abstração de dados, parametridade relacional e equivalência contextual etc. é útil no trabalho diário. Por exemplo, se estou estendendo o software com um novo recurso, sei que ele ainda precisa preservar a funcionalidade original, o que significa que ele deve se comportar da mesma maneira em todos os contextos antigos, mesmo que faça algo novo no novos contextos. Se eu não soubesse nada sobre equivalência contextual, provavelmente nem seria capaz de enquadrar o problema dessa maneira.

Chegando à sua pergunta sobre pi-calculus, acho que o pi-calculus ainda é um pouco novo demais para encontrar aplicativos no design de linguagem. A página da Wikipedia sobre pi-calculus menciona BPML e occam-pi como projetos de linguagem usando pi-calculus. Mas você também pode consultar as páginas do seu CCS predecessor e outros cálculos de processo, como o CSP, juntar o cálculo e outros, que foram usados ​​em muitos designs de linguagem de programação. Você também pode consultar a seção "Objetos e cálculo de pi" do livro Sangiorgi e Walker para ver como o cálculo de pi se relaciona com as linguagens de programação existentes.


0

Eu gosto de procurar implementações práticas de cálculo de processos na natureza :) (além de ler sobre a teoria).

  1. Os canais assíncronos do Clojure são baseados no CSP: http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html
  2. Golang também possui canais baseados no CSP (este Rich Hickey inspirado para clojure, eu acho): http://www.informit.com/articles/printerfriendly/1768317
  3. Há um cara que fez uma extensão baseada em ACP para scala (Subscript), mas eu não tenho reputação suficiente para postar o link ...

etc.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.