O Lisp ainda possui algum recurso especial que NÃO foi adotado por outras linguagens de programação?

35

O Lisp ainda possui algum recurso especial que NÃO foi adotado por outras linguagens de programação?

Por Lisp, quero dizer todas as linguagens de programação Lisp como um todo. Disseram-me como o Lisp é incrível e sei que muitas línguas foram inspiradas pelo Lisp. Mas o Lisp ainda possui algum recurso de design exclusivo que simplesmente não pode ser feito em nenhum outro idioma?

A razão pela qual eu fiz a pergunta é que recentemente, como programador amador, comecei a aprender Clojure apenas por diversão, e o resultado é que encontrei muitas postagens e comentários relacionados ao Lisp, dizendo apenas uma coisa: "Lisp é único ", mas outras linguagens de programação modernas já adotaram e roubaram muitas idéias do Lisp, como condicionais, recursão e a função de cidadão de primeira classe. E até a metaprogramação pode ser feita em vários idiomas.

Perdi alguma coisa e "Lisp ainda é diferente"?

Ou tenho sorte porque outras línguas modernas roubaram todas as partes boas do Lisp, de modo que não é necessário cavar o mundo do Lisp entre parênteses e "Lisp era diferente".

iceX
fonte
3
Compartilhar sua pesquisa ajuda a todos. Conte-nos o que você tentou e por que ele não atendeu às suas necessidades. Isso demonstra que você reservou um tempo para tentar ajudar a si mesmo, evita reiterar respostas óbvias e, acima de tudo, ajuda a obter uma resposta mais específica e relevante. Veja também How to Ask
gnat
3
Thx @gnat para o conselho, e eu atualizei a minha pergunta :)
ICEX
10
Um problema é que, uma vez que uma linguagem possui um certo subconjunto de recursos do Lisp (por exemplo, expressões S e macros), as pessoas afirmam que é um Lisp. O que obviamente tem a conseqüência de que (de acordo com essas pessoas) nenhuma linguagem não-Lisp pode ter esses recursos.
9
Eu acho que não há nenhuma outra língua, onde parênteses são a única forma de agrupar por tudo :-)
Doc Brown
O Lisp como uma família pode não ser muito único, mas muitos dialetos de Lisp (Racket, CL, Scheme, Clojure) ainda oferecem muitos recursos úteis / exclusivos.
Daniel Gratzer

Respostas:

28

Uma referência canônica para esse tipo de pergunta é o What Made Lisp Different, de Paul Graham . Os dois principais recursos restantes do Lisp que não estão amplamente disponíveis, de acordo com este artigo no momento da redação deste documento, são:

8. Uma notação para código usando árvores de símbolos.

9. Todo o idioma sempre disponível. Não há distinção real entre tempo de leitura, tempo de compilação e tempo de execução. Você pode compilar ou executar código durante a leitura, ler ou executar código durante a compilação e ler ou compilar código em tempo de execução.

O comentário aborda cada ponto e nomeia os idiomas populares onde esse recurso está disponível.

8, que (com 9) é o que torna possíveis as macros do Lisp, ainda é exclusivo do Lisp, talvez porque (a) exija esses parênteses, ou algo igualmente ruim, e (b) se você adicionar esse incremento final de poder , você não pode mais alegar ter inventado um novo idioma, mas apenas ter projetado um novo dialeto do Lisp; -)

Observe que este artigo foi revisado pela última vez em 2002 e, nos últimos 11 anos, houve uma grande variedade de novos idiomas, alguns dos quais podem incorporar todos esses recursos do Lisp em seu design.

Greg Hewgill
fonte
2
Esses recursos não são exclusivos do Lisp (e de variantes derivadas diretamente) e não duram muito tempo.
Donal Fellows
21
@iceX: A diferença entre JavaScript e linguagens como Lisp, Smalltalk, Self, Newspeak, APL, Factor, Forth etc. é que, em JavaScript, os programas estão "mortos". Eles são arquivos de texto. Você mata o programa em execução, edita o arquivo de texto e inicia uma cópia completamente nova do programa. Nesses outros (chamados ambientes "animados"), você nunca para o programa em execução, o próprio programa em execução é um conjunto de objetos na memória que você manipula da mesma maneira que manipula qualquer outro objeto enquanto estiver em execução . (Nota: isto não é verdade para Clojure, mas a maioria Lisps mais velhos fazê-lo desta forma.)
Jörg W Mittag
2
@ JörgWMittag Wow ... Então, linguagens de programação como Clojure, Clojurescript, lispyscript não são, de fato, "lisps reais" porque não podem alterar seu código da mesma forma que o Lisp da velha escola, como o Common Lisp. Mas ... se eles não podem mudar isso ... por que se incomodar em usar a expressão S que eu pensava ser para fins de manipulação de código ... (sentindo como se eu
tivesse
4
@iceX: Muitas línguas têm evalou similar, e algumas podem fazer metaprogramação, por exemplo, Haskell, modelo de Haskell. O (indiscutivelmente) único do Lisp é que a representação para dados, código e meta-código é a mesma - não apenas na sintaxe, mas na verdade é a mesma coisa.
tdammers
2
O @iceX Eval é apenas uma parte, mas não é tudo. No Lisp, você pode executar o código em tempo de compilação. Você pode executar o código no tempo de leitura. Sim, o clojure suporta todo o dinamismo do Lisp, possui macros, macros de leitor e avaliação, além da capacidade de anexar um REPL a um programa em execução para modificá-lo em tempo real.
stonemetal
15

A pergunta é difícil de responder, pois alguém precisaria conhecer todos os idiomas para saber que nenhum outro possui um recurso específico disponível no Lisp. Portanto, o seguinte é baseado nos idiomas com os quais tenho experiência.

De cabeça para baixo, condições são algo que eu não vi em nenhum outro idioma. Pense em 'exceções', mas onde a pilha de chamadas não é desenrolada e onde o chamador pode enviar um valor de recuperação para o site da exceção, mas sem perturbar a pilha de chamadas entre o manipulador e a origem da exceção. Para ser justo, isso é realmente apenas uma aplicação especial de continuações, para que Ruby e Scheme (pelo menos) possam fazer isso.

O sistema macro de Lisp se beneficia da regularidade / homoiconicidade, mas Scala planeja incorporá-los como um recurso estável na 2.12 e o Template Haskell reivindica recursos semelhantes. Eu diria que eles serão mais sintaticamente complexos do que com o Lisp, mas a geração de código em tempo de compilação está lá independentemente.

No entanto, pensando bem, a construção direta de formulários é apenas um tipo de macro disponível no Lisp: nunca vi um equivalente de macros de compilador ou leitor em nenhum outro lugar.

A capacidade de alguns dialetos (por exemplo, SBCL ) de salvar uma imagem de processo completa e recuperável é legal, mas, novamente, não é única: o Smalltalk faz isso há décadas.

Muitas outras linguagens permitem a atribuição de desestruturação ao retornar matrizes, mas a abordagem # 'values ​​e #' multiple-value-bind / let-values ​​ainda parece ser específica para Common Lisp and Scheme (que ainda pode fazer a desestruturação 'regular' também ) O 'wantarray' de Perl permite que uma função determine se está sendo chamada em um contexto escalar, de lista ou vazio, para que possa ajustar seu valor de retorno de uma maneira (-ish) semelhante, mas eu não vi vários valores de retorno 'verdadeiros' fora do esquema / CL.

Em termos de recursos de idioma, provavelmente não há muito o que o Lisp possa fazer que outros idiomas não possam (a integridade de Turing é o que é). O que é , no entanto, é uma linguagem em que o código é expresso em termos de suas próprias estruturas de dados, tornando a Big Idea ™ - esse código são dados - algo relativamente fácil de trabalhar.

Danny Woods
fonte
3
As macros Scala são muito menos poderosas que as macros Lisp, bem como as macros TH, macros higiênicas de esquema etc. Um sistema igualmente poderoso pode ser encontrado no MetaLua e no Converge.
SK-logic
4

Depois de tantas décadas, acho que não há nada exclusivo no Lisp. Mas ainda hoje existem muitas coisas interessantes que são difíceis de encontrar fora de Lisps. Algumas coisas que vêm à mente:

  • Um sistema de objetos de alta qualidade com meta-protocolos sofisticados (ou seja, CLOS) não é remotamente popular.
  • de vez em quando aparecem vários métodos, mas a maioria das pessoas nunca ouviu falar sobre eles.
  • Como outros já apontaram, o sistema de condições é bastante sofisticado em comparação aos mecanismos populares de tratamento de exceções.
  • Uma representação compacta da semântica da linguagem (eval), uma abordagem capacitadora para definir a linguagem e disponibilizá-la para adaptações profundas diretas (consulte SICP ) - funções "eval" das atuais linguagens populares simplesmente não compartilham as mesmas propriedades.

Finalmente, há muito mais a aprender com o Lisp que não é sobre o idioma em si, mas se tornou parte da história do Lisp e se perdeu no tempo. Por exemplo, Interlisp, Symbolics Genera, etc ... se você nunca colocar as mãos em Genera, consulte este tópico comp.lang.lisp em que Kent Pitman descreve como "o Emacs é apenas uma sombra pálida do Zmacs do Genera" - que foi habilitado por ter um poderoso sistema Lisp do qual o Zmacs fazia parte, que rodava em uma máquina Lisp.

Thiago Silva
fonte
Eu nunca vi uma boa explicação dos métodos múltiplos que os distinguiam dos métodos sobrecarregados , um recurso padrão em quase todas as linguagens imperativas modernas, exceto pelo fato de que o envio de métodos múltiplos é resolvido dinamicamente no tempo de execução e, portanto, é muito mais lento que o uso de métodos sobrecarregados, que são resolvidos em tempo de compilação.
Mason Wheeler
Eles têm distinções importantes. Se você estiver em recurso constatação de problemas em que, você sempre pode criar uma nova pergunta aqui ..
Thiago Silva
Julia tem vários métodos, e o polimorfismo paramétrico de Haskell é uma espécie de multimétodo. Existem maneiras de simular vários métodos em vários idiomas. O sistema de condições é algo que eu realmente quero especialmente (editar e continuar, embora eu tenha visto isso para depuradores de C #).
aoeu256 14/09
4

Não é necessariamente uma característica única . É toda a aparência e o modo como certos conjuntos de recursos funcionam juntos.

JavaScript ou Java têm muitos recursos do Lisp (máquina virtual, compilador / avaliador, coleta de lixo, etc.). Mas o JavaScript, por exemplo, carece da parte simbólica da programação, carece de recursos matemáticos (internamente, possui apenas flutuadores), carece de tratamento de erros e assim por diante.

Muitos sistemas Common Lisp são otimizados para uma maneira de desenvolvimento, na qual se estende um novo software de forma incremental, estendendo a linguagem Lisp em várias dimensões usando várias técnicas de metaprogramação - sem reiniciar o software por um longo tempo. Portanto, ele precisa ser flexível e extensível - mas, ao mesmo tempo, precisa ser robusto. Alterar o idioma (macros são basicamente uma maneira de o usuário estender o compilador) sem travar o programa.

Agora, algo como JavaScript também é usado para estender um programa, normalmente um navegador da web. Mas, na maioria das vezes, não há muita meta-programação em JavaScript - além de alguns hackers OOP .

Exemplo:

Pode-se implementar um software geral de matemática avançada para o domínio da álgebra computacional de duas maneiras: escrever o mecanismo em C com uma linguagem especializada no topo (como o Mathematica ) ou em algum dialeto Lisp mais avançado. Macsyma / Maxima em Lisp comum, Reduzir em Lisp padrão, Axioma em Lisp comum.

(Também há um ou mais escritos em Python.)

Não existem muitos sistemas que ofereçam o conjunto de recursos do Axiom , que roda sobre o Common Lisp.

O que tornou o Lisp atraente para esses tipos de aplicativos é uma mistura de recursos: matemática básica avançada (bignums, proporções, ...), computação simbólica, compilador interativo etc. É bem possível obter essas coisas implementando-as em um linguagem de nível. Dessa forma, um terá implementado 50% ou mais de um sistema Lisp típico.

Rainer Joswig
fonte
2

Não tanto quanto eu sei. O Forth é facilmente tão dinâmico quanto o Lisp, talvez mais porque o código dinâmico do Forth se parece com o código Forth regular, enquanto as macros do Lisp tendem a usar recursos diferentes do código Lisp normal (no Clojure, pelo menos, nunca usei aspas de sintaxe fora de uma macro) e Como resultado, eles parecem realmente diferentes do código Lisp comum. Como um exemplo de quão dinâmico é o Forth, aqui está uma maneira de implementar comentários no Forth :

: (   41 word drop ; immediate
( That was the definition for the comment word. )
( Now we can add comments to what we are doing! )
pedregoso
fonte
11
Por mais divertido que Forth pareça ser, eu sempre achei irremediavelmente opaco e desajeitado, talvez porque seja baseado em pilha e tudo seja revertido.
Robert Harvey
2
Por curiosidade, o que você quer dizer com 'segregado da parte principal da língua'? As macros no Lisp têm acesso total a todas as funções definidas no ponto em que a macro está definida, qualquer uma das quais pode ser usada para criar o formulário para o qual a macro se expande. Isso pode envolver informações recuperadas de um banco de dados e / ou servidor. Seu exemplo de comentário pode ser definido como: (comentário defmacro (e resto do corpo)), não é?
9139 Danny Woods
11
@DannyWoods, quero dizer que macros não se parecem com código regular. Pelo menos no clojure, você pode distinguir o código macro do código regular, porque ele usa fortemente aspas de sintaxe, emenda entre aspas, etc., o que é incomum no código regular. Esse exemplo de código que forneci parece código normal até você ver o imediato. Relendo minha resposta, ela está mal expressa.
stonemetal
11
@stonemetal Não se preocupe, mas vale a pena notar que não há nada macro-específico na citação de sintaxe, no Common Lisp ou no Clojure. Às vezes, é conveniente ter expressões de backtick em definições de funções regulares, e os corpos de macro podem ser criados manualmente com listas simples (embora você só precise fazer isso uma ou duas vezes para decidir que aspas de sintaxe é uma coisa boa!)
Danny Woods
11
Para ser justo, o mesmo pode ser feito no Lisp, registrando uma macro de leitor personalizada.
Fjarri 04/09/2013
2

O Lisp possui muitos dialetos e cada um deles possui seu próprio conjunto de recursos. Meu recurso favorito que dificilmente será adotado por qualquer outro idioma é o "spaghetti stack" do Interlisp .

A pilha de espaguete é como um fechamento, mas com esteróides. Ele salva não apenas a função atual, mas todo o contexto até o topo da pilha. Algo como uma co-rotina , exceto que você pode criá-las arbitrariamente, resultando em uma hierarquia de contextos de pilha.

ddyer
fonte
Não sabia que, vamos verificá-la, obrigado pela sua resposta :)
ICEX
7
É o mesmo que as continuações de Scheme?
Nicola Musatti
11
@NicolaMusatti, uma "pilha de espaguete" é uma estratégia de implementação comum para continuações do tipo Esquema (que pode ser chamada após o retorno da função que os criou).
Alex D