Lisp (linguagem de programação)

Da Wikipédia, a enciclopédia livre
Ir para a navegação Saltar para pesquisar
Lisp
Lisp logo.svg
ParadigmaMultiparadigma : funcional , processual , reflexivo , meta
Projetado porJohn McCarthy
DesenvolvedorSteve Russell , Timothy P. Hart e Mike Levin
Apareceu pela primeira vez1958 ; 64 anos atrás ( 1958 )
Disciplina de digitaçãoDinâmico , forte
Dialetos
Influenciado por
IPL
Influenciado

Lisp (historicamente LISP ) é uma família de linguagens de programação com uma longa história e uma notação de prefixo distinta, totalmente entre parênteses . [3] Originalmente especificada em 1958, Lisp é a segunda linguagem de programação de alto nível mais antiga ainda em uso comum. Apenas o Fortran é mais antigo, um ano. [4] [5] Lisp mudou desde seus primeiros dias, e muitos dialetos existiram ao longo de sua história. Hoje, os dialetos Lisp de uso geral mais conhecidos são Racket , Common Lisp , Scheme e Clojure . [citação necessária ]

Lisp foi originalmente criado como uma notação matemática prática para programas de computador , influenciado (embora não originalmente derivado) [6] da notação do cálculo lambda de Alonzo Church . Rapidamente se tornou a linguagem de programação preferida para pesquisa de inteligência artificial (IA). [7] Como uma das primeiras linguagens de programação, Lisp foi pioneira em muitas ideias em ciência da computação , incluindo estruturas de dados em árvore , gerenciamento automático de armazenamento , tipagem dinâmica , condicionais , funções de ordem superior ,recursion , o compilador auto-hospedado , [8] e o loop read–eval–print . [9]

O nome LISP deriva de "Processador LISt". [10] As listas vinculadas são uma das principais estruturas de dados do Lisp , e o código-fonte do Lisp é feito de listas. Assim, os programas Lisp podem manipular o código-fonte como uma estrutura de dados, dando origem aos sistemas de macro que permitem aos programadores criar novas sintaxes ou novas linguagens específicas de domínio incorporadas em Lisp.

A intercambialidade de código e dados dá ao Lisp sua sintaxe instantaneamente reconhecível. Todo o código do programa é escrito como s-expressions ou listas entre parênteses. Uma chamada de função ou forma sintática é escrita como uma lista com o nome da função ou do operador primeiro e os argumentos a seguir; por exemplo, uma função fque recebe três argumentos seria chamada como . (f arg1 arg2 arg3)

História

John McCarthy desenvolveu o Lisp em 1958 enquanto estava no Massachusetts Institute of Technology (MIT). McCarthy publicou seu projeto em um artigo na Communications of the ACM em 1960, intitulado "Funções recursivas de expressões simbólicas e sua computação por máquina, parte I". [11] Ele mostrou que com alguns operadores simples e uma notação para funções anônimas emprestadas de Church, pode-se construir uma linguagem Turing-completa para algoritmos.

A Information Processing Language foi a primeira linguagem de IA , de 1955 ou 1956, e já incluía muitos dos conceitos, como processamento de listas e recursão, que passaram a ser usados ​​em Lisp.

A notação original de McCarthy usava " expressões M " entre colchetes que seriam traduzidas em expressões S. Como exemplo, a expressão M car[cons[A,B]]é equivalente à expressão S . Uma vez que o Lisp foi implementado, os programadores rapidamente optaram por usar expressões S, e as expressões M foram abandonadas. As expressões M surgiram novamente com tentativas de curta duração de MLisp [12] por Horace Enea e CGOL por Vaughan Pratt . (car (cons A B))

Lisp foi implementado pela primeira vez por Steve Russell em um computador IBM 704 usando cartões perfurados . [13] Russell leu o artigo de McCarthy e percebeu (para surpresa de McCarthy) que a função eval de Lisp poderia ser implementada em código de máquina .

De acordo com McCarthy: [14]

Steve Russell disse, olha, por que eu não programo essa avaliação  ... e eu disse a ele, ho, ho, você está confundindo teoria com prática, essa avaliação é para leitura, não para computação. Mas ele foi em frente e fez isso. Ou seja, ele compilou o eval em meu artigo em código de máquina IBM 704 , corrigindo bugs , e então anunciou isso como um interpretador Lisp, o que certamente era. Então nesse ponto Lisp tinha essencialmente a forma que tem hoje...

O resultado foi um interpretador Lisp funcional que poderia ser usado para executar programas Lisp, ou mais apropriadamente, "avaliar expressões Lisp".

Duas macros de linguagem assembly para o IBM 704 tornaram-se as operações primitivas para decompor listas: car( Conteúdo da parte Endereço do número do Registro) e cdr( Conteúdo da parte Decrement do número do Registro), [15] onde "registro" refere-se aos registros do unidade de processamento central do computador (CPU). Os dialetos Lisp ainda usam care cdr( / k ɑːr / e / k ʊ d ər /) para as operações que retornam o primeiro item de uma lista e o restante da lista, respectivamente.

O primeiro compilador Lisp completo, escrito em Lisp, foi implementado em 1962 por Tim Hart e Mike Levin no MIT, e poderia ser compilado simplesmente tendo um interpretador LISP existente interpretando o código do compilador, produzindo uma saída de código de máquina capaz de ser executada em 40 -vez melhoria na velocidade sobre a do intérprete. [16] Este compilador introduziu o modelo Lisp de compilação incremental , no qual funções compiladas e interpretadas podem se misturar livremente. A linguagem usada no memorando de Hart e Levin é muito mais próxima do estilo Lisp moderno do que o código anterior de McCarthy.

As rotinas de coleta de lixo foram desenvolvidas pelo estudante de pós-graduação do MIT Daniel Edwards , antes de 1962. [ 17 ]

Durante as décadas de 1980 e 1990, um grande esforço foi feito para unificar o trabalho em novos dialetos Lisp (principalmente sucessores de Maclisp como ZetaLisp e NIL (Nova Implementação de Lisp) em um único idioma. O novo idioma, Common Lisp , era um pouco compatível com os dialetos que substituiu (o livro Common Lisp the Language observa a compatibilidade de várias construções) Em 1994, ANSI publicou o padrão Common Lisp, "ANSI X3.226-1994 Information Technology Programming Language Common Lisp".

Linha do tempo

1955 1960 1965 1970 1975 1980 1985 1990 1995 2000 2005 2010 2015 2020
 LISP 1, 1.5, LISP 2 (abandonado)
 Maclisp
 Interlisp
 MDL
 Lisp Máquina Lisp
 Esquema  R5RS  R6RS  R7RS pequeno
 NADA
 ZIL (Linguagem de Implementação Zork)
 Franz Lisp
 Lisp comum
 Le Lisp
 Esquema do MIT
 T
 Esquema Chez
 Emacs Lisp
 AutoLISP
 PicoLisp
 EuLisp
 ISLISP
 OpenLisp
 Esquema PLT  Raquete
 GNU Guile
 Visual LISP
 Clojure
 Arco
 LFE
 Hy

Conexão com inteligência artificial

Desde o início, Lisp esteve intimamente ligado à comunidade de pesquisa em inteligência artificial , especialmente em sistemas PDP-10 [18] . Lisp foi usado como a implementação da linguagem Micro Planner , que foi usada no famoso sistema de IA SHRDLU . Na década de 1970, quando a pesquisa de IA gerou ramificações comerciais, o desempenho dos sistemas Lisp existentes tornou-se um problema crescente. [ citação necessária ]

Genealogia e variantes

Ao longo de seus sessenta anos de história, Lisp gerou muitas variações sobre o tema central de uma linguagem de expressão S. Além disso, cada dialeto pode ter várias implementações—por exemplo, há mais de uma dúzia de implementações de Common Lisp .

As diferenças entre os dialetos podem ser bastante visíveis - por exemplo, Common Lisp usa a palavra-chave defunpara nomear uma função, mas Scheme usa define. [19] Dentro de um dialeto que é padronizado, no entanto, implementações em conformidade suportam a mesma linguagem central, mas com diferentes extensões e bibliotecas.

Dialetos historicamente significativos

  • LISP 1 [20] – Primeira implementação.
  • LISP 1.5 [21] – Primeira versão amplamente distribuída, desenvolvida por McCarthy e outros no MIT. Assim chamado porque continha várias melhorias no interpretador "LISP 1" original, mas não foi uma grande reestruturação como o planejado LISP 2 seria.
  • Stanford LISP 1.6 [22] – Este foi um sucessor do LISP 1.5 desenvolvido no Stanford AI Lab e amplamente distribuído para sistemas PDP-10 que executam o sistema operacional TOPS-10 . Tornou-se obsoleto por Maclisp e InterLisp.
  • MACLISP [23] – desenvolvido para o Projeto MAC do MIT , o MACLISP é um descendente direto do LISP 1.5. Ele funcionou nos sistemas PDP-10 e Multics . O MACLISP viria a ser chamado mais tarde Maclisp, e é muitas vezes referido como MacLisp. O "MAC" em MACLISP não está relacionado nem ao Macintosh da Apple nem ao McCarthy .
  • Interlisp [24] – desenvolvido na BBN Technologies para sistemas PDP-10 rodando o sistema operacional TENEX , mais tarde adotado como Lisp "Costa Oeste" para as máquinas Xerox Lisp como InterLisp-D . Uma pequena versão chamada "InterLISP 65" foi publicada para a linha de computadores da família Atari de 8 bits baseada em 6502 . Por algum tempo, Maclisp e InterLisp foram fortes concorrentes.
  • Franz Lisp – originalmente um projeto da Universidade da Califórnia, Berkeley ; posteriormente desenvolvido por Franz Inc. O nome é uma deformação humorística do nome " Franz Liszt ", e não se refere ao Allegro Common Lisp , o dialeto de Common Lisp vendido por Franz Inc., em anos mais recentes.
  • XLISP , no qual o AutoLISP foi baseado.
  • Standard Lisp e Portable Standard Lisp foram amplamente utilizados e portados, especialmente com o Sistema de Álgebra Computacional REDUCE.
  • ZetaLisp , também denominado Lisp Machine Lisp – utilizado nas máquinas Lisp , descendente direto do Maclisp. ZetaLisp teve uma grande influência no Common Lisp.
  • LeLisp é um dialeto francês Lisp. Um dos primeiros Construtores de Interface (chamado Interface SOS [25] ) foi escrito em LeLisp.
  • Esquema (1975). [26]
  • Common Lisp (1984), conforme descrito por Common Lisp the Language – uma consolidação de várias tentativas divergentes (ZetaLisp, Spice Lisp , NIL e S-1 Lisp ) para criar dialetos sucessores [27] para Maclisp, com influências substantivas do Scheme dialeto também. Esta versão do Common Lisp estava disponível para diversas plataformas e foi aceita por muitos como um padrão de fato [28] até a publicação do ANSI Common Lisp (ANSI X3.226-1994). Entre os sub-dialetos mais difundidos do Common Lisp estão o Steel Bank Common Lisp(SBCL), CMU Common Lisp (CMU-CL), Clozure OpenMCL (não confundir com Clojure!), GNU CLisp e versões posteriores de Franz Lisp; todos eles aderem ao padrão ANSI CL posterior (veja abaixo).
  • Dylan foi em sua primeira versão uma mistura de Scheme com o Common Lisp Object System.
  • EuLisp – tentativa de desenvolver um novo Lisp eficiente e limpo.
  • ISLISP – tentativa de desenvolver um novo Lisp eficiente e limpo. Padronizado como ISO/IEC 13816:1997 [29] e posteriormente revisado como ISO/IEC 13816:2007: [30] Tecnologia da informação – Linguagens de programação, seus ambientes e interfaces de software do sistema – Linguagem de programação ISLISP .
  • Esquema IEEE – padrão IEEE, 1178–1990 (R1995).
  • ANSI Common Lisp – um padrão do American National Standards Institute (ANSI) para Common Lisp, criado pelo subcomitê X3J13 , fretado [31] para começar com Common Lisp: The Language como um documento base e trabalhar através de um processo de consenso público para encontrar soluções para questões compartilhadas de portabilidade de programas e compatibilidade de implementações de Common Lisp. Embora formalmente um padrão ANSI, a implementação, venda, uso e influência do ANSI Common Lisp foi e continua sendo visto em todo o mundo.
  • ACL2 ou "A Computational Logic for Applicative Common Lisp", uma variante de aplicativo (sem efeitos colaterais) do Common LISP. ACL2 é uma linguagem de programação que pode modelar sistemas de computador e uma ferramenta para ajudar a provar as propriedades desses modelos.
  • Clojure , um dialeto recente do Lisp que compila para a máquina virtual Java e tem um foco particular na simultaneidade .
  • Game Oriented Assembly Lisp (ou GOAL) é uma linguagem de programação de videogame desenvolvida por Andy Gavin e a equipe Jak and Daxter da Naughty Dog . Foi escrito usando Allegro Common Lisp e usado no desenvolvimento de toda a série de jogos Jak and Daxter .
  • Chialisp, um dialeto de alto nível compilado para CLVM, o ambiente de programação on-chain na blockchain Chia

2000 até o presente

Depois de ter declinado um pouco na década de 1990, Lisp experimentou um ressurgimento de interesse após 2000. A maioria das novas atividades tem sido focada em implementações de Common Lisp , Scheme , Emacs Lisp , Clojure e Racket , e inclui o desenvolvimento de novas bibliotecas e aplicativos portáteis.

Muitos novos programadores de Lisp foram inspirados por escritores como Paul Graham e Eric S. Raymond para buscar uma linguagem que outros consideravam antiquada. Novos programadores Lisp frequentemente descrevem a linguagem como uma experiência reveladora e afirmam ser substancialmente mais produtivas do que em outras linguagens. [32] Esse aumento na conscientização pode ser contrastado com o " inverno da IA " e o breve ganho de Lisp em meados da década de 1990. [33]

A partir de 2010 , havia onze implementações de Common Lisp mantidas ativamente. [34] Scieneer Common Lisp é uma nova implementação comercial bifurcada da CMUCL com um primeiro lançamento em 2002.

A comunidade de código aberto criou uma nova infraestrutura de suporte: CLiki é um wiki que coleta informações relacionadas ao Common Lisp, o diretório Common Lisp lista recursos, #lisp é um canal de IRC popular e permite o compartilhamento e comentários de trechos de código (com suporte de lisppaste , um bot de IRC escrito em Lisp), o Planet Lisp coleta o conteúdo de vários blogs relacionados ao Lisp, no LispForum os usuários discutem tópicos do Lisp, o Lispjobs é um serviço para anunciar ofertas de emprego e há um serviço de notícias semanal, Weekly Lisp News . Common-lisp.neté um site de hospedagem para projetos Common Lisp de código aberto. Quicklisp é um gerenciador de biblioteca para Common Lisp.

Cinquenta anos de Lisp (1958–2008) foi comemorado no LISP50@OOPSLA. [35] Há reuniões regulares de usuários locais em Boston, Vancouver e Hamburgo. Outros eventos incluem o European Common Lisp Meeting, o European Lisp Symposium e uma International Lisp Conference.

A comunidade Scheme mantém ativamente mais de vinte implementações . Várias novas implementações significativas (Chicken, Gambit, Gauche, Ikarus, Larceny, Ypsilon) foram desenvolvidas na década de 2000 (década). O Revisado 5 Relatório sobre o Esquema de Linguagem Algorítmica [36] padrão de Scheme foi amplamente aceito na comunidade Scheme. O processo Scheme Requests for Implementation criou muitas bibliotecas e extensões quase padrão para Scheme. As comunidades de usuários de implementações individuais do Scheme continuam a crescer. Um novo processo de padronização linguística foi iniciado em 2003 e levou ao R 6Padrão RS Scheme em 2007. O uso acadêmico do Scheme para o ensino de ciência da computação parece ter diminuído um pouco. Algumas universidades não estão mais usando o Scheme em seus cursos introdutórios de ciência da computação; [37] [38] O MIT agora usa Python em vez de Scheme para seu programa de graduação em ciência da computação e curso on-line aberto massivo do MITx. [39] [40]

Existem vários novos dialetos de Lisp: Arc , Hy , Nu , Liskell e LFE (Lisp Flavored Erlang). O analisador para Julia é implementado em Femtolisp, um dialeto de Scheme (Julia é inspirada em Scheme, que por sua vez é um dialeto de Lisp).

Em outubro de 2019, Paul Graham lançou uma especificação para Bel , “um novo dialeto de Lisp”.

Principais dialetos

Common Lisp e Scheme representam dois grandes fluxos de desenvolvimento de Lisp. Essas linguagens incorporam opções de design significativamente diferentes.

Common Lisp é um sucessor do Maclisp . As principais influências foram Lisp Machine Lisp , Maclisp, NIL , S-1 Lisp , Spice Lisp e Scheme. [41] Ele tem muitos dos recursos do Lisp Machine Lisp (um grande dialeto Lisp usado para programar Lisp Machines ), mas foi projetado para ser implementado de forma eficiente em qualquer computador pessoal ou estação de trabalho. Common Lisp é uma linguagem de programação de uso geral e, portanto, possui um grande padrão de linguagem, incluindo muitos tipos de dados internos, funções, macros e outros elementos de linguagem e um sistema de objetos ( Common Lisp Object System ). Common Lisp também emprestou certos recursos do Scheme, comoescopo lexical e fechamentos lexicais . Implementações de Common Lisp estão disponíveis para direcionar diferentes plataformas , como LLVM , [42] Java virtual machine , [43] x86-64, PowerPC, Alpha, ARM, Motorola 68000 e MIPS, [44] e sistemas operacionais como Windows , macOS, Linux, Solaris, FreeBSD, NetBSD, OpenBSD, Dragonfly BSD e Heroku. [45]

Scheme é um dialeto com escopo estático e propriamente recursivo de cauda da linguagem de programação Lisp inventada por Guy L. Steele, Jr. e Gerald Jay Sussman . Ele foi projetado para ter uma semântica excepcionalmente clara e simples e poucas maneiras diferentes de formar expressões. Projetado cerca de uma década antes do Common Lisp, Scheme é um design mais minimalista. Ele tem um conjunto muito menor de recursos padrão, mas com certos recursos de implementação (como otimização de chamada de cauda e continuações completas) não especificado em Common Lisp. Uma ampla variedade de paradigmas de programação, incluindo estilos imperativos, funcionais e de passagem de mensagens, encontra expressão conveniente no Scheme. Scheme continua a evoluir com uma série de padrões (Revised n Report on the Algorithmic Language Scheme) e uma série de Scheme Requests for Implementation .

Clojure é um dialeto recente de Lisp que tem como alvo principalmente a máquina virtual Java e o Common Language Runtime (CLR), o Python VM, o Ruby VM YARV e a compilação para JavaScript . Ele foi projetado para ser uma linguagem pragmática de propósito geral. Clojure extrai influências consideráveis ​​de Haskell e coloca uma ênfase muito forte na imutabilidade. [46] Clojure fornece acesso a frameworks e bibliotecas Java, com dicas de tipo opcionais e inferência de tipo , para que chamadas para Java possam evitar reflexão e permitir operações primitivas rápidas. Clojure não foi projetado para ser compatível com outros dialetos Lisp.[47]

Além disso, os dialetos Lisp são usados ​​como linguagens de script em muitos aplicativos, sendo o mais conhecido o Emacs Lisp no editor Emacs , AutoLISP e depois Visual Lisp no AutoCAD , Nyquist no Audacity e Scheme no LilyPond . O tamanho pequeno potencial de um interpretador de Scheme útil o torna particularmente popular para scripts incorporados. Exemplos incluem SIOD e TinyScheme , ambos os quais foram incorporados com sucesso no processador de imagem GIMP sob o nome genérico "Script-fu". [48]LIBREP, um interpretador Lisp de John Harper originalmente baseado na linguagem Emacs Lisp , foi incorporado no gerenciador de janelas Sawfish . [49]

Dialetos padronizados

Lisp tem dialetos oficialmente padronizados: R6RS Scheme , R7RS Scheme , IEEE Scheme, [50] ANSI Common Lisp e ISO ISLISP .

Inovações linguísticas

Lisp foi a primeira linguagem em que a estrutura do código do programa é representada fiel e diretamente em uma estrutura de dados padrão - uma qualidade muito mais tarde apelidada de " homiconicidade ". Assim, as funções Lisp podem ser manipuladas, alteradas ou mesmo criadas dentro de um programa Lisp sem manipulações de nível inferior. Isso geralmente é considerado uma das principais vantagens da linguagem no que diz respeito ao seu poder expressivo, e torna a linguagem adequada para macros sintáticas e avaliação metacircular .

Uma condicional usando uma sintaxe if-then-else foi inventada por McCarthy em um contexto Fortran. Ele propôs sua inclusão no ALGOL , mas não fez parte da especificação Algol 58 . Para Lisp, McCarthy usou a estrutura cond mais geral . [51] Algol 60 pegou if–then–else e o popularizou.

Lisp influenciou profundamente Alan Kay , o líder da equipe de pesquisa que desenvolveu Smalltalk na Xerox PARC ; e, por sua vez, o Lisp foi influenciado pelo Smalltalk, com dialetos posteriores adotando recursos de programação orientada a objetos (classes de herança, instâncias de encapsulamento, passagem de mensagens, etc.) na década de 1970. O sistema de objetos Flavors introduziu o conceito de herança múltipla e o mixin . O Common Lisp Object System fornece herança múltipla, multimétodos com despacho múltiplo e funções genéricas de primeira classe , produzindo uma forma flexível e poderosa de despacho dinâmico. Ele serviu como modelo para muitos sistemas de objetos Lisp (incluindo Scheme ) subsequentes, que são frequentemente implementados por meio de um protocolo metaobjeto , um design metacircular reflexivo no qual o sistema de objetos é definido em termos de si mesmo: Lisp foi apenas a segunda linguagem após Smalltalk (e ainda é uma das poucas linguagens) a possuir tal sistema metaobjeto. Muitos anos depois, Alan Kay sugeriu que, como resultado da confluência desses recursos, apenas Smalltalk e Lisp poderiam ser considerados sistemas de programação orientados a objetos adequadamente concebidos. [52]

Lisp introduziu o conceito de coleta de lixo automática , na qual o sistema percorre o heap procurando por memória não utilizada. O progresso em algoritmos de coleta de lixo sofisticados modernos, como coleta de lixo geracional, foi estimulado por seu uso em Lisp. [53]

Edsger W. Dijkstra em sua palestra do Prêmio Turing de 1972 disse:

"Com alguns princípios muito básicos em sua fundação, [LISP] mostrou uma estabilidade notável. Além disso, LISP tem sido o portador de um número considerável de nossos aplicativos de computador mais sofisticados. LISP foi jocosamente descrito como " a maneira mais inteligente de fazer mau uso de um computador”. Acho essa descrição um grande elogio porque transmite todo o sabor da libertação: ajudou vários de nossos companheiros humanos mais talentosos a pensar em pensamentos anteriormente impossíveis." [54]

Em grande parte por causa de seus requisitos de recursos em relação ao hardware de computação inicial (incluindo os primeiros microprocessadores), o Lisp não se tornou tão popular fora da comunidade de IA quanto o Fortran e a linguagem C descendente do ALGOL . Devido à sua adequação a aplicações complexas e dinâmicas, Lisp está desfrutando de algum ressurgimento de interesse popular na década de 2010. [55]

Sintaxe e semântica

Nota : Os exemplos deste artigo estão escritos em Common Lisp (embora a maioria também seja válida em Scheme ).

Expressões simbólicas (expressões S)

Lisp é uma linguagem orientada a expressões . Ao contrário da maioria das outras linguagens, nenhuma distinção é feita entre "expressões" e "declarações" ; [ duvidoso ] todo código e dados são escritos como expressões. Quando uma expressão é avaliada , ela produz um valor (em Common Lisp, possivelmente vários valores), que pode ser incorporado em outras expressões. Cada valor pode ser qualquer tipo de dados.

O artigo de McCarthy de 1958 introduziu dois tipos de sintaxe: Expressões simbólicas ( S-expressions , sexps), que espelham a representação interna de código e dados; e Metaexpressões ( M-expressions ), que expressam funções de S-expressions. As expressões-M nunca foram favorecidas, e quase todos os Lisps hoje usam expressões-S para manipular tanto o código quanto os dados.

O uso de parênteses é a diferença mais óbvia do Lisp em relação a outras famílias de linguagens de programação. Como resultado, os alunos há muito atribuem apelidos ao Lisp, como Lost In Stupid Parênteses ou Muitos Parênteses Supérfluos Irritantes . [56] No entanto, a sintaxe da expressão S também é responsável por grande parte do poder do Lisp: a sintaxe é simples e consistente, o que facilita a manipulação pelo computador. No entanto, a sintaxe do Lisp não se limita à notação tradicional de parênteses. Pode ser estendido para incluir notações alternativas. Por exemplo, XMLisp é uma extensão Common Lisp que emprega o protocolo metaobject para integrar expressões S com a Extensible Markup Language ( XML ).

A dependência de expressões dá à linguagem grande flexibilidade. Como as funções Lisp são escritas como listas, elas podem ser processadas exatamente como dados. Isso permite a escrita fácil de programas que manipulam outros programas ( metaprogramação ). Muitos dialetos Lisp exploram esse recurso usando sistemas de macro, o que permite a extensão da linguagem quase sem limites.

Listas

Uma lista Lisp é escrita com seus elementos separados por espaços em branco e entre parênteses. Por exemplo, é uma lista cujos elementos são os três átomos , , e . Esses valores são tipados implicitamente: eles são respectivamente dois inteiros e um tipo de dados específico do Lisp chamado "símbolo", e não precisam ser declarados como tal. (1 2 foo) 12foo

A lista vazia ()também é representada como o átomo especial nil. Esta é a única entidade em Lisp que é tanto um átomo quanto uma lista.

As expressões são escritas como listas, usando notação de prefixo . O primeiro elemento da lista é o nome de uma função, o nome de uma macro, uma expressão lambda ou o nome de um "operador especial" (veja abaixo). O restante da lista são os argumentos. Por exemplo, a função listretorna seus argumentos como uma lista, então a expressão

 ( lista  1  2  ( aspas  foo ))

avalia para a lista . A "quote" antes de no exemplo anterior é um "operador especial" que retorna seu argumento sem avaliá-lo. Quaisquer expressões sem aspas são avaliadas recursivamente antes que a expressão envolvente seja avaliada. Por exemplo, (1 2 foo)foo

 ( lista  1  2  ( lista  3  4 ))

avalia para a lista . Observe que o terceiro argumento é uma lista; listas podem ser aninhadas. (1 2 (3 4))

Operadores

Os operadores aritméticos são tratados de forma semelhante. A expressão

 ( +  1  2  3  4 )

é avaliado como 10. O equivalente sob notação infixa seria " ". 1 + 2 + 3 + 4

Lisp não tem noção de operadores como implementados em linguagens derivadas de Algol. Operadores aritméticos em Lisp são funções variádicas (ou n-ary ), capazes de receber qualquer número de argumentos. Um operador de incremento '++' no estilo C às vezes é implementado sob o nome incfque fornece a sintaxe

 ( incf  x )

equivalente a (setq x (+ x 1)), retornando o novo valor de x.

"Operadores especiais" (às vezes chamados de "formulários especiais") fornecem a estrutura de controle do Lisp. Por exemplo, o operador especial ifrecebe três argumentos. Se o primeiro argumento for diferente de zero, ele será avaliado como o segundo argumento; caso contrário, ele avalia o terceiro argumento. Assim, a expressão

 ( if  nil 
     ( lista  1  2  "foo" ) 
     ( lista  3  4  "bar" ))

avalia para . Claro, isso seria mais útil se uma expressão não trivial tivesse sido substituída no lugar de . (3 4 "bar")nil

Lisp também fornece operadores lógicos and , or and not . Os operadores and e or fazem uma avaliação de curto-circuito e retornarão seu primeiro argumento nulo e não nulo, respectivamente.

 ( ou  ( e  "zero"  nil  "nunca" )  "James"  'tarefa  'tempo )

será avaliado como "James".

Expressões lambda e definição de função

Outro operador especial, lambda, é usado para vincular variáveis ​​a valores que são então avaliados em uma expressão. Este operador também é usado para criar funções: os argumentos para lambdasão uma lista de argumentos e a expressão ou expressões para as quais a função avalia (o valor retornado é o valor da última expressão avaliada). A expressão

 ( lambda  ( arg )  ( +  arg  1 ))

avalia uma função que, quando aplicada, recebe um argumento, associa-o arge retorna o número um maior que esse argumento. As expressões lambda não são tratadas de forma diferente das funções nomeadas; eles são invocados da mesma maneira. Portanto, a expressão

 (( lambda  ( arg )  ( +  arg  1 ))  5 )

avalia para 6. Aqui, estamos fazendo uma aplicação de função: executamos a função anônima passando para ela o valor 5.

As funções nomeadas são criadas armazenando uma expressão lambda em um símbolo usando a macro defun.

 ( defun  foo  ( a  b  c  d )  ( +  a  b  c  d ))

(defun f (a) b...)define uma nova função nomeada fno ambiente global. É conceitualmente semelhante à expressão:

 ( setf  ( fdefinição  'f )  #' ( lambda  ( a )  ( bloco  f  b... )))

onde setfé uma macro usada para definir o valor do primeiro argumento para um novo objeto de função. é uma definição de função global para a função chamada . é uma abreviação de operador especial, retornando um objeto de função. fdefinition 'ffdefinitionf#'function

Átomos

No LISP original havia dois tipos de dados fundamentais : átomos e listas. Uma lista era uma sequência finita ordenada de elementos, onde cada elemento é um átomo ou uma lista, e um átomo era um número ou um símbolo. Um símbolo era essencialmente um item nomeado exclusivo, escrito como uma string alfanumérica no código-fonte e usado como um nome de variável ou como um item de dados no processamento simbólico . Por exemplo, a lista contém três elementos: o símbolo , a lista e o número 2. (FOO (BAR 1) 2)FOO(BAR 1)

A diferença essencial entre átomos e listas era que os átomos eram imutáveis ​​e únicos. Dois átomos que apareciam em lugares diferentes no código-fonte, mas eram escritos exatamente da mesma maneira, representavam o mesmo objeto, [ carece de fontes ] enquanto que cada lista era um objeto separado que podia ser alterado independentemente de outras listas e podia ser distinguido de outras listas por operadores de comparação.

À medida que mais tipos de dados foram introduzidos nos dialetos Lisp posteriores e os estilos de programação evoluíram, o conceito de átomo perdeu importância. [ carece de fontes ] Muitos dialetos ainda retinham o predicado atom para compatibilidade com o legado , [ carece de fontes ] definindo-o verdadeiro para qualquer objeto que não seja um contra.

Conses e listas

Diagrama de caixa e ponteiro para a lista (42 69 613)

Uma lista Lisp é implementada como uma lista encadeada simples . [57] Cada célula desta lista é chamada de cons (em Scheme, um par ) e é composta por dois ponteiros , chamados de car e cdr . Eles são respectivamente equivalentes aos campos datae discutidos na lista vinculada do artigo . next

Das muitas estruturas de dados que podem ser construídas a partir de células contra, uma das mais básicas é chamada de lista adequada . Uma lista adequada é o nilsímbolo especial (lista vazia) ou um contra no qual os carpontos apontam para um dado (que pode ser outra estrutura contra, como uma lista) e os cdrpontos para outra lista adequada.

Se um determinado contra for considerado o início de uma lista encadeada, seu carro apontará para o primeiro elemento da lista e seu cdr apontará para o restante da lista. Por esta razão, as funções care cdrtambém são chamadas firste restquando se referem a conses que fazem parte de uma lista encadeada (em vez de, digamos, uma árvore).

Assim, uma lista Lisp não é um objeto atômico, como seria uma instância de uma classe container em C++ ou Java. Uma lista nada mais é do que um agregado de conses vinculados. Uma variável que se refere a uma determinada lista é simplesmente um ponteiro para os primeiros contras da lista. A travessia de uma lista pode ser feita reduzindo a lista; ou seja, levando cdrs sucessivos para visitar cada contra da lista; ou usando qualquer uma das várias funções de ordem superior para mapear uma função em uma lista.

Como os conses e as listas são tão universais em sistemas Lisp, é um equívoco comum que eles sejam as únicas estruturas de dados do Lisp. Na verdade, todos, exceto os Lisps mais simplistas, têm outras estruturas de dados, como vetores ( arrays ), tabelas de hash , estruturas e assim por diante.

Expressões S representam listas

As expressões S entre parênteses representam estruturas de lista vinculada. Existem várias maneiras de representar a mesma lista como uma expressão S. Um cons pode ser escrito em notação de par pontilhado como , onde é o carro e o cdr. Uma lista adequada mais longa pode ser escrita em notação de par pontilhado. Isso é convencionalmente abreviado como na notação de lista . Uma lista imprópria [58] pode ser escrita em uma combinação dos dois – como para a lista de três conses cujo último cdr é (isto é, a lista na forma totalmente especificada). (a . b)ab(a . (b . (c . (d . nil))))(a b c d)(a b c . d)d(a . (b . (c . d)))

Procedimentos de processamento de listas

Lisp fornece muitos procedimentos internos para acessar e controlar listas. As listas podem ser criadas diretamente com o listprocedimento, que recebe qualquer número de argumentos e retorna a lista desses argumentos.

 ( lista  1  2  'a  3 ) 
 ;Saída: (1 2 a 3)
 ( lista  1  ' ( 2  3 )  4 ) 
 ;Saída: (1 (2 3) 4)

Devido à maneira como as listas são construídas a partir de cons pairs , o consprocedimento pode ser usado para adicionar um elemento à frente de uma lista. Observe que o consprocedimento é assimétrico na forma como lida com argumentos de lista, devido à forma como as listas são construídas.

 ( contras  1  ' ( 2  3 )) 
 ;Saída: (1 2 3)
 ( contras  ' ( 1  2 )  ' ( 3  4 )) 
 ;Saída: ((1 2) 3 4)

O appendprocedimento anexa duas (ou mais) listas uma à outra. Como as listas Lisp são listas vinculadas, anexar duas listas tem complexidade de tempo assintótica

 ( anexar  ' ( 1  2 )  ' ( 3  4 )) 
 ; Saída: (1 2 3 4)
 ( anexar  ' ( 1  2  3 )  ' ()  ' ( a )  ' ( 5  6 )) 
 ; Saída: (1 2 3 a 5 6)

Estrutura compartilhada

As listas Lisp, sendo simples listas vinculadas, podem compartilhar estrutura umas com as outras. Ou seja, duas listas podem ter a mesma cauda , ​​ou sequência final de conses. Por exemplo, após a execução do seguinte código Common Lisp:

( setf  foo  ( list  'a  'b  'c )) 
( setf  bar  ( contras  'x  ( cdr  foo )))

as listas fooe barsão e respectivamente. No entanto, a cauda é a mesma estrutura em ambas as listas. Não é uma cópia; as células cons apontando para e estão nos mesmos locais de memória para ambas as listas. (a b c)(x b c)(b c)bc

Compartilhamento de estrutura em vez de cópia pode proporcionar uma melhoria dramática no desempenho. No entanto, esta técnica pode interagir de forma indesejada com funções que alteram listas passadas a elas como argumentos. Alterar uma lista, como substituir o cpor a goose, afetará a outra:

 ( setf  ( terceiro  foo )  'ganso )

Isso muda foopara , mas também muda para – um resultado possivelmente inesperado. Isso pode ser uma fonte de bugs, e funções que alteram seus argumentos são documentadas como destrutivas por esse motivo. (a b goose)bar(x b goose)

Os aficionados da programação funcional evitam funções destrutivas. No dialeto Scheme, que favorece o estilo funcional, os nomes das funções destrutivas são marcados com um ponto de exclamação de advertência, ou "bang" - como set-car!(leia set car bang ), que substitui o carro de um contra. No dialeto Common Lisp, as funções destrutivas são comuns; o equivalente de set-car!é nomeado rplacapara "substituir carro". Essa função raramente é vista, no entanto, pois o Common Lisp inclui um recurso especial, setf, para facilitar a definição e o uso de funções destrutivas. Um estilo frequente no Common Lisp é escrever código funcionalmente (sem chamadas destrutivas) durante a prototipagem e, em seguida, adicionar chamadas destrutivas como uma otimização onde for seguro fazê-lo.

Formulários de autoavaliação e cotação

Lisp avalia expressões que são inseridas pelo usuário. Símbolos e listas são avaliados para alguma outra expressão (geralmente mais simples) – por exemplo, um símbolo avalia o valor da variável que ele nomeia; avalia para . No entanto, a maioria dos outros formulários avaliam a si mesmos: se entrar em Lisp, ele retorna . (+ 2 3)555

Qualquer expressão também pode ser marcada para evitar que seja avaliada (como é necessário para símbolos e listas). Este é o papel do quoteoperador especial, ou sua abreviação '(uma aspa). Por exemplo, geralmente ao inserir o símbolo foo, ele retorna o valor da variável correspondente (ou um erro, se não houver tal variável). Para se referir ao símbolo literal, digite ou, geralmente, . (quote foo)'foo

Tanto Common Lisp quanto Scheme também suportam o operador backquote (denominado quasiquote em Scheme), inserido com o `caractere ( acento grave ). Isso é quase o mesmo que aspas simples, exceto que permite que expressões sejam avaliadas e seus valores interpolados em uma lista entre aspas com os operadores vírgula , unquote e vírgula-at ,@ splice . Se a variável snuetem o valor , então avalia como , enquanto avalia como . O backquote é mais frequentemente usado na definição de expansões de macro. [59] [60](bar baz)`(foo ,snue)(foo (bar baz))`(foo ,@snue)(foo bar baz)

Os formulários de autoavaliação e os formulários citados são o equivalente de literais do Lisp. Pode ser possível modificar os valores de literais (mutáveis) no código do programa. Por exemplo, se uma função retorna um formulário entre aspas e o código que chama a função modifica o formulário, isso pode alterar o comportamento da função em invocações subsequentes.

( defun  deve ser constante  () 
  ' ( um  dois  três ))

( let  (( stuff  ( should-be-constant ))) 
  ( setf  ( third  stuff )  'bizarre ))    ; ruim!

( deve ser constante )    ; retornos (um dois bizarros)

Modificar um formulário citado como este geralmente é considerado um estilo ruim e é definido pelo ANSI Common Lisp como errôneo (resultando em comportamento "indefinido" em arquivos compilados, porque o compilador de arquivos pode unir constantes semelhantes, colocá-los na memória protegida contra gravação, etc.).

A formalização da citação de Lisp foi observada por Douglas Hofstadter (em Gödel, Escher, Bach ) e outros como um exemplo da ideia filosófica de auto-referência .

Escopo e encerramento

A família Lisp se divide no uso de escopo dinâmico ou estático (também conhecido como léxico) . Clojure, Common Lisp e Scheme fazem uso de escopo estático por padrão, enquanto newLISP , Picolisp e as linguagens incorporadas em Emacs e AutoCAD usam escopo dinâmico. Desde a versão 24.1, o Emacs usa escopo dinâmico e léxico.

Estrutura da lista do código do programa; exploração por macros e compiladores

Uma distinção fundamental entre Lisp e outras linguagens é que em Lisp, a representação textual de um programa é simplesmente uma descrição legível por humanos das mesmas estruturas de dados internas (listas vinculadas, símbolos, números, caracteres, etc.) o sistema Lisp subjacente.

Lisp usa isso para implementar um sistema de macro muito poderoso. Como outras linguagens de macro, como a definida pelo pré- processador C (o pré-processador de macro para as linguagens de programação C , Objective-C e C++ ), uma macro retorna código que pode ser compilado. No entanto, ao contrário das macros do pré-processador C, as macros são funções Lisp e, portanto, podem explorar todo o poder do Lisp.

Além disso, como o código Lisp tem a mesma estrutura que as listas, as macros podem ser criadas com qualquer uma das funções de processamento de lista na linguagem. Em resumo, qualquer coisa que o Lisp possa fazer com uma estrutura de dados, as macros do Lisp podem fazer com o código. Em contraste, na maioria das outras linguagens, a saída do analisador é puramente interna à implementação da linguagem e não pode ser manipulada pelo programador.

Esse recurso facilita o desenvolvimento de linguagens eficientes dentro de linguagens. Por exemplo, o Common Lisp Object System pode ser implementado de forma limpa como uma extensão de linguagem usando macros. Isso significa que, se um aplicativo precisar de um mecanismo de herança diferente, ele poderá usar um sistema de objetos diferente. Isso contrasta fortemente com a maioria das outras linguagens; por exemplo, Java não suporta herança múltipla e não há uma maneira razoável de adicioná-la.

Em implementações simplistas de Lisp, essa estrutura de lista é interpretada diretamente para executar o programa; uma função é literalmente uma parte da estrutura de lista que é percorrida pelo interpretador ao executá-la. No entanto, os sistemas Lisp mais substanciais também incluem um compilador. O compilador traduz a estrutura da lista em código de máquina ou bytecode para execução. Esse código pode ser executado tão rápido quanto o código compilado em linguagens convencionais, como C.

As macros se expandem antes da etapa de compilação e, portanto, oferecem algumas opções interessantes. Se um programa precisa de uma tabela pré-computada, uma macro pode criar a tabela em tempo de compilação, de modo que o compilador precisa apenas produzir a tabela e não precisa chamar o código para criar a tabela em tempo de execução. Algumas implementações de Lisp possuem até um mecanismo, eval-when, que permite que o código esteja presente durante o tempo de compilação (quando uma macro precisa dele), mas não presente no módulo emitido. [61]

Avaliação e o loop read-eval-print

As linguagens Lisp são frequentemente usadas com uma linha de comando interativa , que pode ser combinada com um ambiente de desenvolvimento integrado (IDE). O usuário digita expressões na linha de comando ou direciona o IDE para transmiti-las ao sistema Lisp. Lisp as expressões inseridas, avalia -as e imprime o resultado. Por esse motivo, a linha de comando Lisp é chamada de loop read–eval–print ( REPL ).

A operação básica do REPL é a seguinte. Esta é uma descrição simplista que omite muitos elementos de um Lisp real, como citações e macros.

A readfunção aceita expressões S textuais como entrada e as analisa em uma estrutura de dados interna. Por exemplo, se você digitar o texto no prompt, traduz isso em uma lista vinculada com três elementos: o símbolo , o número 1 e o número 2. Acontece que essa lista também é uma parte válida do código Lisp; isto é, pode ser avaliado. Isso ocorre porque o carro da lista nomeia uma função – a operação de adição. (+ 1 2)read+

Observe que a fooserá lido como um único símbolo. 123será lido como o número cento e vinte e três. "123"será lida como a string "123".

A evalfunção avalia os dados, retornando zero ou mais dados Lisp como resultado. A avaliação não precisa significar interpretação; alguns sistemas Lisp compilam cada expressão para código de máquina nativo. É simples, no entanto, descrever avaliação como interpretação: para avaliar uma lista cujo carro nomeia uma função, evalprimeiro avalia cada um dos argumentos fornecidos em seu cdr e, em seguida, aplica a função aos argumentos. Nesse caso, a função é adição e aplicá-la à lista de argumentos produz a resposta . Este é o resultado da avaliação. (1 2)3

O símbolo fooavalia o valor do símbolo foo. Dados como a string "123" são avaliados para a mesma string. A lista avalia a lista (1 2 3). (quote (1 2 3))

É o trabalho da printfunção representar a saída para o usuário. Para um resultado simples como 3este é trivial. Uma expressão avaliada para uma parte da estrutura da lista exigiria que printpercorresse a lista e a imprimisse como uma expressão S.

Para implementar um REPL Lisp, é necessário apenas implementar essas três funções e uma função de loop infinito. (Naturalmente, a implementação de evalserá complexa, pois também deve implementar todos os operadores especiais como ifou lambda.) Feito isso, um REPL básico é uma linha de código: . (loop (print (eval (read))))

O Lisp REPL normalmente também fornece edição de entrada, um histórico de entrada, tratamento de erros e uma interface para o depurador.

Lisp é geralmente avaliado com entusiasmo . Em Common Lisp , os argumentos são avaliados na ordem do aplicativo ('leftmost innermost'), enquanto em Scheme a ordem dos argumentos é indefinida, deixando espaço para otimização por um compilador.

Estruturas de controle

Lisp originalmente tinha muito poucas estruturas de controle, mas muitas outras foram adicionadas durante a evolução da linguagem. (O operador condicional original de Lisp, cond, é o precursor de if-then-elseestruturas posteriores.)

Os programadores no dialeto Scheme geralmente expressam loops usando a recursão de cauda . A semelhança do Scheme na ciência da computação acadêmica levou alguns alunos a acreditar que a recursão da cauda é a única, ou a mais comum, maneira de escrever iterações em Lisp, mas isso está incorreto. Todos os dialetos Lisp vistos com frequência têm construções de iteração no estilo imperativo, desde o doloop do Scheme até as expressões complexas do Common Lisp . loopAlém disso, a questão-chave que torna isso um assunto objetivo e não subjetivo é que o Scheme faz requisitos específicos para o tratamento de chamadas de cauda, e, portanto, o motivo pelo qual o uso de recursão de cauda é geralmente incentivado para Scheme é que a prática é expressamente suportada pela definição da linguagem. Por outro lado, o ANSI Common Lisp não requer [62] a otimização comumente chamada de eliminação de chamada de cauda. Assim, o fato de que o estilo recursivo da cauda como um substituto casual para o uso de construções de iteração mais tradicionais (como do, dolistou loop) é desencorajado [63] em Common Lisp não é apenas uma questão de preferência estilística, mas potencialmente de eficiência (uma vez que uma chamada de cauda aparente no Common Lisp pode não compilar como um simples salto ) e a correção do programa (já que a recursão de cauda pode aumentar o uso da pilha no Common Lisp, arriscandoestouro de pilha ).

Algumas estruturas de controle Lisp são operadores especiais , equivalentes a palavras-chave sintáticas de outras linguagens. As expressões que usam esses operadores têm a mesma aparência de superfície que as chamadas de função, mas diferem porque os argumentos não são necessariamente avaliados — ou, no caso de uma expressão de iteração, podem ser avaliados mais de uma vez.

Em contraste com a maioria das outras linguagens de programação, Lisp permite implementar estruturas de controle usando a linguagem. Várias estruturas de controle são implementadas como macros Lisp, e podem até ser macro-expandidas pelo programador que queira saber como elas funcionam.

Tanto o Common Lisp quanto o Scheme possuem operadores para fluxo de controle não local. As diferenças nesses operadores são algumas das diferenças mais profundas entre os dois dialetos. Scheme suporta continuações reentrantes usando o call/ccprocedimento, que permite que um programa salve (e depois restaure) um local específico em execução. Common Lisp não suporta continuações reentrantes, mas suporta várias maneiras de lidar com continuações de escape.

Muitas vezes, o mesmo algoritmo pode ser expresso em Lisp em um estilo imperativo ou funcional. Como observado acima, Scheme tende a favorecer o estilo funcional, usando recursão de cauda e continuações para expressar o fluxo de controle. No entanto, o estilo imperativo ainda é bem possível. O estilo preferido por muitos programadores de Common Lisp pode parecer mais familiar para programadores acostumados a linguagens estruturadas como C, enquanto o preferido por Schemers se assemelha mais a linguagens puramente funcionais como Haskell .

Por causa da herança inicial do Lisp no processamento de listas, ele possui uma ampla variedade de funções de ordem superior relacionadas à iteração sobre sequências. Em muitos casos em que um loop explícito seria necessário em outras linguagens (como um forloop em C) em Lisp, a mesma tarefa pode ser realizada com uma função de ordem superior. (O mesmo vale para muitas linguagens de programação funcionais.)

Um bom exemplo é uma função que em Scheme é chamada mape em Common Lisp é chamada mapcar. Dada uma função e uma ou mais listas, mapcaraplica a função sucessivamente aos elementos das listas em ordem, coletando os resultados em uma nova lista:

 ( mapcar  # ' +  ' ( 1  2  3  4  5 )  ' ( 10  20  30  40  50 ))

Isso aplica a +função a cada par correspondente de elementos da lista, produzindo o resultado . (11 22 33 44 55)

Exemplos

Aqui estão exemplos de código Common Lisp.

O programa básico " Olá, mundo! ":

( imprima  "Olá, Mundo!" )

A sintaxe Lisp se presta naturalmente à recursão. Problemas matemáticos como a enumeração de conjuntos definidos recursivamente são simples de expressar nesta notação. Por exemplo, para avaliar o fatorial de um número :

( defun  fatorial  ( n ) 
    ( if  ( zerop  n )  1 
        ( *  n  ( fatorial  ( 1-  n ))))))

Uma implementação alternativa ocupa menos espaço de pilha do que a versão anterior se o sistema Lisp subjacente otimizar a recursão da cauda :

( defun  fatorial  ( n  &opcional  ( acc  1 )) 
    ( if  ( zerop  n )  acc 
        ( fatorial  ( 1-  n )  ( *  acc  n )))))

Compare os exemplos acima com uma versão iterativa que usa a macro do Common Lisp :loop

( defun  fatorial  ( n ) 
    ( loop  para  i  de  1  a  n 
        para  fac  =  1  então  ( *  fac  i ) 
        finalmente  ( return  fac )))

A função a seguir inverte uma lista. (A função reversa integrada do Lisp faz a mesma coisa.)

( defun  -reverse  ( lista ) 
    ( let  (( valor de retorno )) 
      ( dolist  ( e  lista )  ( push  e  valor de retorno )) 
      valor de retorno ))

Sistemas de objetos

Vários sistemas de objetos e modelos foram construídos em cima, ao lado ou no Lisp, incluindo:

Sistemas operacionais

Vários sistemas operacionais , incluindo sistemas baseados em linguagem , são baseados em Lisp (use recursos Lisp, convenções, métodos, estruturas de dados, etc.), ou são escritos em Lisp, [66] incluindo:

Genera , renomeado Open Genera, [67] pela Symbolics ; Medley, escrito em Interlisp, originalmente uma família de sistemas operacionais gráficos que rodavam nas estações de trabalho Star da Xerox ; [68] [69] Mezano; [70] Provisório; [71] [72] ChrysaLisp, [73] por desenvolvedores do TAOS da Tao Systems; [74] e o Urbit muito parecido com Lisp, [75] usando a tecnologia de criptomoeda Ethereum. [76]

Veja também

Referências

  1. ^ "Introdução" . O Manual de Júlia . Leia os Documentos. Arquivado a partir do original em 2016-04-08 . Recuperado 2016-12-10 .
  2. ^ "Perguntas e respostas do Wolfram Language" . Pesquisa Wolfram . Recuperado 2016-12-10 .
  3. ^ Edwin D. Reilly (2003). Marcos em ciência da computação e tecnologia da informação . Grupo Editorial Greenwood. págs. 156-157. ISBN 978-1-57356-521-9.
  4. ^ "SICP: Prefácio" . Arquivado do original em 2001-07-27. Lisp é um sobrevivente, tendo sido usado por cerca de um quarto de século. Entre as linguagens de programação ativas, apenas o Fortran teve uma vida mais longa.
  5. ^ "Conclusões" . Arquivado a partir do original em 2014-04-03 . Recuperado 2014-06-04 .
  6. ^ "A Arte do Intérprete, ou o Complexo Modularidade (Partes Zero, Um e Dois), Parte Zero, P. 4" . Bibliotecas do MIT. hdl : 1721.1/6094 . Recuperado 2020-08-01 .
  7. ^ "As principais linguagens de programação em inteligência artificial" . Inteligência Artificial . APRO. Arquivado a partir do original em 30/10/2020 . Recuperado 2021-02-15 .
  8. ^ Paulo Graham. "A Vingança dos Nerds" . Recuperado 2013-03-14 .
  9. ^ Chisnall, David (2011-01-12). Linguagens de Programação Influentes, Parte 4: Lisp .
  10. ^ Jones, Robin; Maynard, Clive; Stewart, Ian (6 de dezembro de 2012). A Arte da Programação Lisp . Springer Science & Business Media. pág. 2. ISBN 9781447117193.
  11. ^ McCarthy, John. "Funções recursivas de expressões simbólicas e sua computação por máquina, Parte I" . Arquivado a partir do original em 2013-10-04 . Recuperado em 2006-10-13 .
  12. ^ Smith, David Canfield. Manual do Usuário MLISP (PDF) . Recuperado em 2006-10-13 .
  13. ^ McCarthy, John (12 de fevereiro de 1979). "História do Lisp: Laboratório de Inteligência Artificial" (PDF) .
  14. ^ Stoyan, Herbert (1984-08-06). História LISP inicial (1956-1959) . LFP '84: Proceedings of the 1984 ACM Symposium on LISP e programação funcional. Associação de Máquinas de Computação . pág. 307. doi : 10.1145/800055.802047 . Arquivado a partir do original em 2005-04-05.
  15. ^ McCarthy, John. "Pré-história LISP - Verão de 1956 a Verão de 1958" . Recuperado 2010-03-14 .
  16. ^ Hart, Tim; Levin, Mike. "AI Memo 39-O novo compilador" (PDF) . Arquivado a partir do original (PDF) em 13/12/2020 . Recuperado 2019-03-18 .
  17. ^ McCarthy, John; Abrahams, Paul W.; Edwards, Daniel J.; Hart, Timothy P.; Levin, Michael I. (1962, (na 15ª impressão, 1985)). Manual do programador LISP 1.5 (PDF) (2ª ed.). pág. Prefácio. {{cite book}}: Verifique os valores de data em: |date=( ajuda )
  18. O tamanho da palavra de 36 bits do PDP-6 / PDP-10 foi influenciado pela utilidade de ter dois ponteiros Lisp de 18 bits em uma única palavra. Peter J. Hurley (18 de outubro de 1990). "A História do TOPS ou Vida nos Fast ACs" . Grupo de notíciasalt.folklore.computers . Usenet: [email protected] . O projeto PDP-6 começou no início de 1963, como uma máquina de 24 bits. Ele cresceu para 36 bits para LISP, um objetivo de design. 
  19. ^ Common Lisp:(defun f (x) x)
    Esquema:(define f (lambda (x) x))ou(define (f x) x)
  20. ^ McCarthy, J. ; Brayton, R .; Edwards, D .; Fox, P .; Hodes, L .; Luckham, D .; Maling, K .; Parque, D. ; Russell, S. (março de 1960). "Manual de Programadores LISP I" (PDF) . Boston , Massachusetts : Grupo de Inteligência Artificial, Centro de Computação do MIT e Laboratório de Pesquisa. Arquivado a partir do original (PDF) em 17/07/2010. {{cite journal}}:Cite journal requer |journal=( ajuda )Acesso em 11 de maio de 2010.
  21. ^ McCarthy, John; Abrahams, Paul W.; Edwards, Daniel J.; Hart, Timothy P.; Levin, Michael I. (1985) [1962]. Manual do programador LISP 1.5 (PDF) (2ª ed.). Imprensa do MIT . ISBN  0-262-13011-4.
  22. ^ Quam, Lynn H.; Diffle, Whitfield. Manual de Stanford LISP 1.6 (PDF) .
  23. ^ "Manual de Referência Maclisp" . 3 de março de 1979. Arquivado a partir do original em 14/12/2007.
  24. ^ Teitelman, Warren (1974). Manual de referência do InterLisp (PDF) . Arquivado a partir do original (PDF) em 2006-06-02 . Recuperado em 2006-08-19 .
  25. ^ Outils de generation d'interfaces: estado de arte e classificação por H. El Mrabet
  26. ^ Gerald Jay Sussman & Guy Lewis Steele Jr. (dezembro de 1975). "Esquema: um intérprete para cálculo lambda estendido" (PDF) . Memorandos de IA . Laboratório de IA do MIT . AIM-349 . Recuperado em 23 de dezembro de 2021 .
  27. ^ Steele, Guy L., Jr. (1990). "Propósito" . Common Lisp the Language (2ª ed.). ISBN 0-13-152414-3.
  28. ^ Kantrowitz, Mark; Margolin, Barry (20 de fevereiro de 1996). "História: De onde veio Lisp?" . FAQ: Perguntas frequentes sobre Lisp 2/7 .
  29. ^ "ISO/IEC 13816:1997" . Iso.org. 2007-10-01 . Recuperado 2013-11-15 .
  30. ^ "ISO/IEC 13816:2007" . Iso.org. 30-10-2013 . Recuperado 2013-11-15 .
  31. ^ "Carta X3J13" .
  32. ^ "The Road To Lisp Survey" . Arquivado a partir do original em 2006-10-04 . Recuperado em 2006-10-13 .
  33. ^ "Tendências para o futuro" . Faqs.org. Arquivado a partir do original em 2013-06-03 . Recuperado 2013-11-15 .
  34. ^ Weinreb, Daniel. "Implementações do Common Lisp: Uma Pesquisa" . Arquivado a partir do original em 21/04/2012 . Recuperado em 4 de abril de 2012 .
  35. ^ "LISP50@OOPSLA" . Lisp50.org . Recuperado 2013-11-15 .
  36. ^ Documentos: Padrões: R5RS . schemars.org (2012-01-11). Recuperado em 2013-07-17.
  37. ^ "Por que o MIT agora usa python em vez de esquema para seu programa de graduação CS" . cemerick . com . 24 de março de 2009. Arquivado a partir do original em 17 de setembro de 2010 . Recuperado em 10 de novembro de 2013 .
  38. ^ Broder, Evan (8 de janeiro de 2008). "O Fim de uma Era" . mitadmissions.org . Recuperado em 10 de novembro de 2013 .
  39. ^ "Programas de graduação do MIT EECS" . www.eecs.mit.edu . MIT Engenharia Elétrica e Ciência da Computação . Recuperado em 31 de dezembro de 2018 .
  40. ^ "O curso introdutório de Python do MITx atinge 1,2 milhão de matrículas" . MIT EECS . MIT Engenharia Elétrica e Ciência da Computação . Recuperado em 31 de dezembro de 2018 .
  41. ^ Capítulo 1.1.2, História, Padrão ANSI CL
  42. ^ [1] Clasp é uma implementação de Common Lisp que interopera com C++ e usa LLVM para compilação just-in-time (JIT) para código nativo.
  43. ^ [2] "Armed Bear Common Lisp (ABCL) é uma implementação completa da linguagem Common Lisp com um interpretador e um compilador, rodando na JVM"
  44. ^ [3] Arquivado em 22/06/2018 no Wayback Machine Common Lisp Implementations: A Survey
  45. ^ [4] Comparação de implementações de Common Lisp desenvolvidas ativamente
  46. ^ Uma análise detalhada das coleções Clojure , recuperadas em 24/06/2012
  47. ^ "Clojure racional" . Recuperado em 27 de agosto de 2019 . Clojure é um Lisp não restrito pela compatibilidade com versões anteriores
  48. ^ Script-fu no GIMP 2.4 , recuperado em 29/10/2009
  49. ^ librep em Sawfish Wikia, recuperado 2009-10-29
  50. ^ "Esquema IEEE" . IEEE 1178-1990 - Padrão IEEE para a Linguagem de Programação do Esquema . Recuperado em 27 de agosto de 2019 .
  51. ^ "Pré-história LISP - Verão de 1956 a Verão de 1958" . Inventei expressões condicionais em conexão com um conjunto de rotinas de movimentos legais de xadrez que escrevi em FORTRAN para o IBM 704 no MIT durante 1957-58 ... Um artigo definindo expressões condicionais e propondo seu uso em Algol foi enviado para as Comunicações do ACM mas foi arbitrariamente rebaixado a uma carta ao editor, porque era muito curta.
  52. ^ "Significado de 'Programação Orientada a Objetos' de acordo com o Dr. Alan Kay" . 23-07-2003. Eu não entendia a ideia monstruosa do LISP de metalinguagem tangível na época, mas me aproximei das ideias sobre linguagens extensíveis... subestruturas poderosas e mais tardias ... OOP para mim significa apenas mensagens, retenção e proteção local e ocultação do processo de estado e vinculação tardia extrema de todas as coisas. Isso pode ser feito em Smalltalk e em LISP. Existem possivelmente outros sistemas em que isso é possível, mas não estou ciente deles.
  53. ^ Lieberman, Henry; Hewitt, Carl (junho de 1983), "A Real-Time Garbage Collector Based on the Lifetimes of Objects" , Communications of the ACM , 26 (6): 419–429, CiteSeerX 10.1.1.4.8633 , doi : 10.1145/358141.358147 , hdl : 1721.1/6335 , S2CID 14161480  
  54. ^ Edsger W. Dijkstra (1972), The Humble Programmer (EWD 340)(Palestra do Prêmio ACM Turing).
  55. ^ "Um olhar sobre Clojure e o ressurgimento de Lisp" .
  56. ^ "O arquivo jargão - Lisp" . Recuperado em 2006-10-13 .
  57. ^ Sebesta, Robert W. (2012). ""2.4 Programação Funcional: LISP";"6.9 Tipos de Lista";"15.4 A Primeira Linguagem de Programação Funcional: LISP"". Conceitos de Linguagens de Programação (impressão) (10ª ed.). Boston, MA, EUA: Addison-Wesley. pp. 47–52, 281–284, 677–680. ISBN 978-0-13-139531-2.
  58. ^ NB: a chamada "lista pontilhada" é apenas um tipo de "lista imprópria". O outro tipo é a "lista circular", onde as células contras formam um loop. Normalmente, isso é representado usando #n=(...) para representar a célula de contras de destino que terá várias referências, e #n# é usado para se referir a esses contras. Por exemplo, (#1=(ab) . #1#) normalmente seria impresso como ((ab) ab) (sem a impressão de estrutura circular habilitada), mas torna clara a reutilização da célula cons. #1=(a . #1#) normalmente não pode ser impresso, pois é circular, embora (a...) às vezes seja exibido, o CDR da célula cons definida por #1= é ele mesmo.
  59. ^ "CSE 341: Esquema: Citação, Quasiquote e Metaprogramação" . Cs.washington.edu. 22-02-1999 . Recuperado 2013-11-15 .
  60. ^ Quasiquotation in Lisp Arquivado 2013-06-03 no Wayback Machine , Alan Bawden
  61. ^ Tempo de avaliação - extensões comuns do Lisp . Gnu.org. Recuperado em 2013-07-17.
  62. ^ 3.2.2.3 Restrições semânticas em Common Lisp HyperSpec
  63. ^ 4.3. Controle de abstração (recursão vs. iteração) no tutorial sobre o estilo de programação Good Lisp por Kent Pitman e Peter Norvig , agosto de 1993.
  64. ^ página 17 de Bobrow 1986
  65. ^ Veitch, p 108, 1988
  66. Comprovado, Liam (29 de março de 2022). "O mundo selvagem dos sistemas operacionais não-C" . O Registo . Recuperado 2022-02-02 .
  67. ^ "Symbolics Open Genera 2.0" . Arquivo de Internet do GitHub . 7 de janeiro de 2020 . Recuperado 2022-02-02 .
  68. ^ "Projeto Interlisp.org" . Interlisp.org . 15 de março de 2022 . Recuperado 2022-02-02 .
  69. ^ "Interlisp Medley" . GitHub . março de 2022 . Recuperado 2022-02-02 .
  70. ^ froggey (1 de agosto de 2021). "Mezanino" . GitHub . Recuperado 2022-02-02 .
  71. ^ Hartmann, Lukas F. (10 de setembro de 2015). "Provisório" . Interim-os . Recuperado 2022-02-02 .
  72. Hartmann, Lukas F. (11 de junho de 2021). "Provisório" . GitHub . Recuperado 2022-02-02 .
  73. Hinsley, Chris (23 de fevereiro de 2022). "ChrysaLisp" . GitHub . Recuperado 2022-02-02 .
  74. ^ Smith, Tony (21 de agosto de 2013). "UK micro pioneiro Chris Shelton: A mente por trás do Nascom 1" . O Registo . Recuperado 2022-02-02 .
  75. ^ "Um sistema operacional de ardósia limpa e rede para o século 21" . Urbit.org . Recuperado 2022-02-02 .
  76. O'Leary, Rachel-Rose (13 de setembro de 2021). "Urbit está movendo seu servidor virtual Galaxy para o Ethereum" . CoinDesk . Recuperado 2022-02-02 .

Leitura adicional

Links externos

História
Associações e reuniões
Livros e tutoriais
Entrevistas
Recursos