Linguagem de programação - Programming language

O código fonte para um simples programa de computador escrito na linguagem de programação C . As linhas cinzas são comentários que ajudam a explicar o programa aos humanos em uma linguagem natural . Quando compilado e executado , ele fornecerá a saída " Hello, world! ".

Uma linguagem de programação é uma linguagem formal que compreende um conjunto de strings que produzem vários tipos de saída de código de máquina . Linguagens de programação são um tipo de linguagem de computador e são usadas na programação de computadores para implementar algoritmos .

A maioria das linguagens de programação consiste em instruções para computadores . Existem máquinas programáveis ​​que usam um conjunto de instruções específicas , em vez de linguagens de programação gerais . Desde o início de 1800, programas têm sido usados ​​para direcionar o comportamento de máquinas como teares Jacquard , caixas de música e pianos reprodutores . Os programas para essas máquinas (como os pergaminhos de um piano mecânico) não produziram um comportamento diferente em resposta a diferentes entradas ou condições.

Milhares de linguagens de programação diferentes foram criadas e mais estão sendo criadas a cada ano. Muitas linguagens de programação são escritas de forma imperativa (ou seja, como uma sequência de operações a serem executadas), enquanto outras linguagens usam a forma declarativa (ou seja, o resultado desejado é especificado, não como alcançá-lo).

A descrição de uma linguagem de programação é geralmente dividida em dois componentes de sintaxe (forma) e semântica (significado). Algumas linguagens são definidas por um documento de especificação (por exemplo, a linguagem de programação C é especificada por um padrão ISO ), enquanto outras linguagens (como Perl ) têm uma implementação dominante que é tratada como uma referência . Algumas linguagens têm ambos, sendo comum a linguagem básica definida por um padrão e extensões retiradas da implementação dominante.

A teoria da linguagem de programação é um subcampo da ciência da computação que lida com o design, implementação, análise, caracterização e classificação de linguagens de programação.

Definições

Uma linguagem de programação é uma notação para escrever programas , que são especificações de um cálculo ou algoritmo . Alguns autores restringem o termo "linguagem de programação" àquelas linguagens que podem expressar todos os algoritmos possíveis. Características muitas vezes consideradas importantes para o que constitui uma linguagem de programação incluem:

Função e alvo
Uma linguagem de programação de computador é uma linguagem usada para escrever programas de computador , que envolve um computador executando algum tipo de computação ou algoritmo e, possivelmente, controlar dispositivos externos, como impressoras , unidades de disco , robôs e assim por diante. Por exemplo, programas PostScript são freqüentemente criados por outro programa para controlar uma impressora ou monitor de computador. De maneira mais geral, uma linguagem de programação pode descrever a computação em alguma máquina, possivelmente abstrata. É geralmente aceito que uma especificação completa para uma linguagem de programação inclui uma descrição, possivelmente idealizada, de uma máquina ou processador para essa linguagem. Na maioria dos contextos práticos, uma linguagem de programação envolve um computador; conseqüentemente, as linguagens de programação geralmente são definidas e estudadas dessa forma. As linguagens de programação diferem das linguagens naturais porque as linguagens naturais são usadas apenas para interação entre pessoas, enquanto as linguagens de programação também permitem que os humanos comuniquem instruções às máquinas.
Abstrações
Linguagens de programação geralmente contêm abstrações para definir e manipular estruturas de dados ou controlar o fluxo de execução . A necessidade prática de que uma linguagem de programação suporte abstrações adequadas é expressa pelo princípio de abstração . Este princípio às vezes é formulado como uma recomendação ao programador para fazer uso adequado de tais abstrações.
Poder expressivo
A teoria da computação classifica as linguagens pelos cálculos que são capazes de expressar. Todas as linguagens de Turing-complete podem implementar o mesmo conjunto de algoritmos . ANSI / ISO SQL-92 e Charity são exemplos de linguagens que não são Turing completas, embora sejam freqüentemente chamadas de linguagens de programação.

Linguagens de marcação como XML , HTML ou troff , que definem dados estruturados , geralmente não são consideradas linguagens de programação. As linguagens de programação podem, no entanto, compartilhar a sintaxe com as linguagens de marcação se uma semântica computacional for definida. XSLT , por exemplo, é uma linguagem Turing completa que usa inteiramente a sintaxe XML. Além disso, o LaTeX , que é usado principalmente para estruturar documentos, também contém um subconjunto completo de Turing.

O termo linguagem de computador é às vezes usado de forma intercambiável com linguagem de programação. No entanto, o uso de ambos os termos varia entre os autores, incluindo o escopo exato de cada um. Um uso descreve as linguagens de programação como um subconjunto das linguagens de computador. Da mesma forma, as linguagens usadas na computação que têm um objetivo diferente do que expressar programas de computador são genericamente designadas como linguagens de computador. Por exemplo, as linguagens de marcação às vezes são chamadas de linguagens de computador para enfatizar que não devem ser usadas para programação.

Outro uso considera as linguagens de programação como construções teóricas para a programação de máquinas abstratas , e as linguagens de computador como o subconjunto das mesmas que é executado em computadores físicos, que têm recursos de hardware finitos. John C. Reynolds enfatiza que as linguagens de especificação formal são tanto linguagens de programação quanto as linguagens destinadas à execução. Ele também argumenta que os formatos de entrada textuais e mesmo gráficos que afetam o comportamento de um computador são linguagens de programação, apesar do fato de geralmente não serem Turing-completos, e observa que a ignorância dos conceitos das linguagens de programação é a razão para muitas falhas nos formatos de entrada.

História

Desenvolvimentos iniciais

Computadores muito antigos, como o Colossus , eram programados sem a ajuda de um programa armazenado , modificando seus circuitos ou configurando bancos de controles físicos.

Um pouco mais tarde, os programas podem ser escritos em linguagem de máquina , onde o programador escreve cada instrução em uma forma numérica que o hardware pode executar diretamente. Por exemplo, a instrução para adicionar o valor em dois locais de memória pode consistir em 3 números: um "opcode" que seleciona a operação "adicionar" e dois locais de memória. Os programas, em formato decimal ou binário, eram lidos a partir de cartões perfurados , fita de papel, fita magnética ou alternados em interruptores no painel frontal do computador. As linguagens de máquina foram posteriormente denominadas linguagens de programação de primeira geração (1GL).

O próximo passo foi o desenvolvimento das chamadas linguagens de programação de segunda geração (2GL) ou linguagens assembly , que ainda estavam intimamente ligadas à arquitetura do conjunto de instruções do computador específico. Isso serviu para tornar o programa muito mais legível por humanos e aliviar o programador de cálculos de endereço tediosos e sujeitos a erros.

As primeiras linguagens de programação de alto nível , ou linguagens de programação de terceira geração (3GL), foram escritas na década de 1950. Uma das primeiras linguagens de programação de alto nível a ser projetada para um computador foi Plankalkül , desenvolvida para o Z3 alemão por Konrad Zuse entre 1943 e 1945. No entanto, ela não foi implementada até 1998 e 2000.

O Short Code de John Mauchly , proposto em 1949, foi uma das primeiras linguagens de alto nível já desenvolvidas para um computador eletrônico . Ao contrário do código de máquina , as instruções de código curto representavam expressões matemáticas de forma compreensível. No entanto, o programa precisava ser traduzido em código de máquina toda vez que era executado, tornando o processo muito mais lento do que executar o código de máquina equivalente.

Na Universidade de Manchester , Alick Glennie desenvolveu o Autocode no início dos anos 1950. Como linguagem de programação , ele usava um compilador para converter automaticamente a linguagem em código de máquina. O primeiro código e compilador foi desenvolvido em 1952 para o computador Mark 1 na Universidade de Manchester e é considerado a primeira linguagem de programação de alto nível compilada .

O segundo autocode foi desenvolvido para o Mark 1 por RA Brooker em 1954 e foi chamado de "Mark 1 Autocode". Brooker também desenvolveu um autocódigo para o Ferranti Mercury na década de 1950 em conjunto com a Universidade de Manchester. A versão para o EDSAC 2 foi desenvolvida por DF Hartley do University of Cambridge Mathematical Laboratory em 1961. Conhecido como EDSAC 2 Autocode, foi um desenvolvimento direto do Mercury Autocode adaptado para as circunstâncias locais e foi conhecido por sua otimização de código de objeto e linguagem-fonte diagnósticos avançados para a época. Um segmento de desenvolvimento contemporâneo, mas separado, o Atlas Autocode foi desenvolvido para a máquina Atlas 1 da Universidade de Manchester .

Em 1954, o FORTRAN foi inventado na IBM por John Backus . Foi a primeira linguagem de programação de alto nível amplamente usada a ter uma implementação funcional, em oposição a apenas um design no papel. Ainda é uma linguagem popular para computação de alto desempenho e é usada para programas que avaliam e classificam os supercomputadores mais rápidos do mundo .

Outra linguagem de programação inicial foi desenvolvida por Grace Hopper nos Estados Unidos, chamada FLOW-MATIC . Foi desenvolvido para o UNIVAC I na Remington Rand durante o período de 1955 a 1959. Hopper descobriu que os clientes de processamento de dados de negócios se incomodavam com a notação matemática e, no início de 1955, ela e sua equipe escreveram uma especificação para uma linguagem de programação em inglês e implementaram um protótipo. O compilador FLOW-MATIC tornou-se disponível publicamente no início de 1958 e estava substancialmente completo em 1959. FLOW-MATIC foi uma grande influência no design do COBOL , uma vez que apenas ele e seu descendente direto AIMACO estavam em uso na época.

Refinamento

O aumento do uso de linguagens de alto nível introduziu um requisito para linguagens de programação de baixo nível ou linguagens de programação de sistema . Essas linguagens, em vários graus, fornecem facilidades entre linguagens assembly e linguagens de alto nível. Eles podem ser usados ​​para executar tarefas que requerem acesso direto aos recursos de hardware, mas ainda fornecem estruturas de controle de nível superior e verificação de erros.

O período da década de 1960 ao final da década de 1970 trouxe o desenvolvimento dos principais paradigmas de linguagem agora em uso:

Cada uma dessas linguagens gerou descendentes, e a maioria das linguagens de programação modernas conta com pelo menos um deles em sua ancestralidade.

As décadas de 1960 e 1970 também viram um debate considerável sobre os méritos da programação estruturada e se as linguagens de programação deveriam ser projetadas para suportá-la. Edsger Dijkstra , em uma famosa carta de 1968 publicada no Communications of the ACM , argumentou que as declarações Goto deveriam ser eliminadas de todas as linguagens de programação de "nível superior".

Consolidação e crescimento

Uma seleção de livros didáticos que ensinam programação, em linguagens populares e obscuras. Essas são apenas algumas das milhares de linguagens de programação e dialetos que foram projetados na história.

A década de 1980 foi de relativa consolidação. C ++ combinada orientada a objetos e programação de sistemas. O governo dos Estados Unidos padronizou a Ada , uma linguagem de programação de sistemas derivada de Pascal e destinada ao uso por empreiteiros de defesa. No Japão e em outros lugares, grandes somas foram gastas investigando as chamadas linguagens de "quinta geração" que incorporavam construções de programação lógica. A comunidade de linguagens funcionais mudou para padronizar ML e Lisp. Em vez de inventar novos paradigmas, todos esses movimentos se basearam nas ideias inventadas nas décadas anteriores.

Uma tendência importante no projeto de linguagem para a programação de sistemas em grande escala durante a década de 1980 foi um maior foco no uso de módulos ou unidades organizacionais de código em grande escala. Modula-2 , Ada e ML desenvolveram notáveis ​​sistemas de módulos na década de 1980, que muitas vezes eram associados a construções de programação genéricas .

O rápido crescimento da Internet em meados da década de 1990 criou oportunidades para novos idiomas. Perl , originalmente uma ferramenta de script Unix lançada pela primeira vez em 1987, tornou-se comum em sites dinâmicos . Java passou a ser usado para programação do lado do servidor, e as máquinas virtuais de bytecode tornaram-se populares novamente em ambientes comerciais com sua promessa de " Escreva uma vez, execute em qualquer lugar " ( UCSD Pascal foi popular por um tempo no início dos anos 1980). Esses desenvolvimentos não eram fundamentalmente novos; em vez disso, eram refinamentos de muitas linguagens e paradigmas existentes (embora sua sintaxe fosse freqüentemente baseada na família C de linguagens de programação).

A evolução da linguagem de programação continua, tanto na indústria quanto na pesquisa. As direções atuais incluem verificação de segurança e confiabilidade , novos tipos de modularidade ( mixins , delegados , aspectos ) e integração de banco de dados como o LINQ da Microsoft .

Linguagens de programação de quarta geração (4GL) são linguagens de programação de computador que visam fornecer um nível mais alto de abstração dos detalhes do hardware interno do computador do que 3GLs. As linguagens de programação de quinta geração (5GL) são linguagens de programação baseadas na resolução de problemas usando restrições fornecidas ao programa, em vez de usar um algoritmo escrito por um programador.

Elementos

Todas as linguagens de programação têm alguns blocos de construção primitivos para a descrição dos dados e os processos ou transformações aplicadas a eles (como a adição de dois números ou a seleção de um item de uma coleção). Essas primitivas são definidas por regras sintáticas e semânticas que descrevem sua estrutura e significado, respectivamente.

Sintaxe

Analise a árvore do código Python com tokenização de inserção
O realce de sintaxe é freqüentemente usado para ajudar os programadores a reconhecer os elementos do código-fonte. A linguagem acima é Python .

A forma de superfície de uma linguagem de programação é conhecida como sua sintaxe . A maioria das linguagens de programação são puramente textuais; eles usam sequências de texto incluindo palavras, números e pontuação, bem como as línguas naturais escritas. Por outro lado, existem algumas linguagens de programação que são de natureza mais gráfica , usando relações visuais entre símbolos para especificar um programa.

A sintaxe de uma linguagem descreve as possíveis combinações de símbolos que formam um programa sintaticamente correto. O significado dado a uma combinação de símbolos é tratado pela semântica ( formal ou codificada em uma implementação de referência ). Como a maioria dos idiomas é textual, este artigo discute a sintaxe textual.

A sintaxe da linguagem de programação é geralmente definida usando uma combinação de expressões regulares (para estrutura lexical ) e a forma Backus – Naur (para estrutura gramatical ). Abaixo está uma gramática simples, baseada em Lisp :

expression ::= atom | list
atom       ::= number | symbol
number     ::= [+-]?['0'-'9']+
symbol     ::= ['A'-'Z''a'-'z'].*
list       ::= '(' expression* ')'

Esta gramática especifica o seguinte:

  • uma expressão é um átomo ou uma lista ;
  • um átomo é um número ou um símbolo ;
  • um número é uma sequência ininterrupta de um ou mais dígitos decimais, opcionalmente precedido por um sinal de mais ou menos;
  • um símbolo é uma letra seguida por zero ou mais de quaisquer caracteres (excluindo espaços em branco); e
  • uma lista é um par de parênteses correspondente, com zero ou mais expressões dentro dela.

O que se segue são exemplos de sequências de token bem formadas neste gramática: 12345, ()e (a b c232 (1)).

Nem todos os programas sintaticamente corretos são semanticamente corretos. Muitos programas sintaticamente corretos são malformados, de acordo com as regras da linguagem; e pode (dependendo da especificação do idioma e da solidez da implementação) resultar em um erro na tradução ou execução. Em alguns casos, esses programas podem exibir um comportamento indefinido . Mesmo quando um programa está bem definido em uma linguagem, ele ainda pode ter um significado que não foi pretendido pela pessoa que o escreveu.

Usando a linguagem natural como exemplo, pode não ser possível atribuir um significado a uma frase gramaticalmente correta ou a frase pode ser falsa:

O fragmento da linguagem C a seguir está sintaticamente correto, mas executa operações que não são semanticamente definidas (a operação *p >> 4não tem significado para um valor de tipo complexo e p->imnão é definida porque o valor de pé o ponteiro nulo ):

complex *p = NULL;
complex abs_p = sqrt(*p >> 4 + p->im);

Se a declaração de tipo na primeira linha fosse omitida, o programa dispararia um erro na variável indefinida pdurante a compilação. No entanto, o programa ainda estaria sintaticamente correto, pois as declarações de tipo fornecem apenas informações semânticas.

A gramática necessária para especificar uma linguagem de programação pode ser classificada por sua posição na hierarquia de Chomsky . A sintaxe da maioria das linguagens de programação pode ser especificada usando uma gramática Tipo 2, ou seja, são gramáticas livres de contexto . Algumas linguagens, incluindo Perl e Lisp, contêm construções que permitem a execução durante a fase de análise. As linguagens que possuem construções que permitem ao programador alterar o comportamento do analisador tornam a análise de sintaxe um problema indecidível e geralmente confundem a distinção entre análise e execução. Em contraste com o sistema de macro do Lisp e os BEGINblocos do Perl , que podem conter cálculos gerais, as macros C são meramente substituições de strings e não requerem execução de código.

Semântica

O termo semântica se refere ao significado das línguas, em oposição à sua forma ( sintaxe ).

Semântica estática

A semântica estática define restrições na estrutura de textos válidos que são difíceis ou impossíveis de expressar em formalismos sintáticos padrão. Para linguagens compiladas, a semântica estática inclui essencialmente aquelas regras semânticas que podem ser verificadas em tempo de compilação. Os exemplos incluem verificar se cada identificador é declarado antes de ser usado (em linguagens que exigem tais declarações) ou se os rótulos nos braços de uma instrução case são distintos. Muitas restrições importantes deste tipo, como verificar se os identificadores são usados ​​no contexto apropriado (por exemplo, não adicionar um número inteiro ao nome de uma função), ou se as chamadas de sub-rotina têm o número e tipo de argumentos apropriados, podem ser aplicadas definindo-os como regras em uma lógica chamada sistema de tipos . Outras formas de análises estáticas, como análise de fluxo de dados, também podem fazer parte da semântica estática. Linguagens de programação mais recentes como Java e C # têm análise de atribuição definida , uma forma de análise de fluxo de dados, como parte de sua semântica estática.

Semântica dinâmica

Uma vez que os dados tenham sido especificados, a máquina deve ser instruída a realizar operações nos dados. Por exemplo, a semântica pode definir a estratégia pela qual as expressões são avaliadas como valores, ou a maneira pela qual as estruturas de controle executam declarações condicionalmente . A semântica dinâmica (também conhecida como semântica de execução ) de uma linguagem define como e quando as várias construções de uma linguagem devem produzir um comportamento de programa. Existem muitas maneiras de definir a semântica de execução. A linguagem natural é freqüentemente usada para especificar a semântica de execução de linguagens comumente usadas na prática. Uma quantidade significativa de pesquisa acadêmica foi para a semântica formal das linguagens de programação , que permitem que a semântica de execução seja especificada de maneira formal. Os resultados deste campo de pesquisa têm visto aplicação limitada ao projeto e implementação de linguagens de programação fora da academia.

Sistema de tipo

Um sistema de tipos define como uma linguagem de programação classifica valores e expressões em tipos , como pode manipular esses tipos e como eles interagem. O objetivo de um sistema de tipos é verificar e geralmente impor um certo nível de correção em programas escritos nessa linguagem, detectando certas operações incorretas. Qualquer sistema de tipo decidível envolve uma troca: embora rejeite muitos programas incorretos, ele também pode proibir alguns programas corretos, embora incomuns. Para contornar essa desvantagem, várias linguagens têm lacunas de tipo , geralmente conversões não verificadas que podem ser usadas pelo programador para permitir explicitamente uma operação normalmente não permitida entre tipos diferentes. Na maioria das linguagens tipadas, o sistema de tipos é usado apenas para programas de verificação de digitação , mas várias linguagens, geralmente funcionais, inferem tipos , dispensando o programador da necessidade de escrever anotações de tipo. O projeto formal e o estudo dos sistemas de tipos são conhecidos como teoria dos tipos .

Linguagens digitadas versus não digitadas

Uma linguagem é digitada se a especificação de cada operação define os tipos de dados aos quais a operação é aplicável. Por exemplo, os dados representados por "this text between the quotes"são uma string e, em muitas linguagens de programação, dividir um número por uma string não tem significado e não será executado. A operação inválida pode ser detectada quando o programa é compilado (verificação de tipo "estático") e será rejeitada pelo compilador com uma mensagem de erro de compilação, ou pode ser detectada enquanto o programa está sendo executado (verificação de tipo "dinâmico"), resultando em uma exceção de tempo de execução . Muitas linguagens permitem que uma função chamada manipulador de exceções trate essa exceção e, por exemplo, sempre retorne "-1" como resultado.

Um caso especial de linguagens digitadas são as linguagens de tipo único . Freqüentemente, são linguagens de script ou marcação, como REXX ou SGML , e têm apenas um tipo de dados - cadeias de caracteres mais comumente usadas para dados simbólicos e numéricos.

Em contraste, uma linguagem sem tipo, como a maioria das linguagens assembly , permite que qualquer operação seja realizada em quaisquer dados, geralmente sequências de bits de vários comprimentos. As linguagens não tipadas de alto nível incluem BCPL , Tcl e algumas variedades de Forth .

Na prática, embora poucos idiomas sejam considerados digitados a partir da teoria dos tipos (verificando ou rejeitando todas as operações), a maioria dos idiomas modernos oferece um certo grau de digitação. Muitas linguagens de produção fornecem meios para contornar ou subverter o sistema de tipos, trocando a segurança de tipos por um controle mais preciso sobre a execução do programa (consulte casting ).

Tipagem estática versus dinâmica

Na tipagem estática , todas as expressões têm seus tipos determinados antes de quando o programa é executado, normalmente em tempo de compilação. Por exemplo, 1 e (2 + 2) são expressões inteiras; eles não podem ser passados ​​para uma função que espera uma string ou armazenados em uma variável que é definida para conter datas.

Linguagens tipadas estaticamente podem ser digitadas manifestamente ou inferidas por tipo . No primeiro caso, o programador deve escrever explicitamente tipos em certas posições textuais (por exemplo, em declarações de variáveis ). No segundo caso, o compilador infere os tipos de expressões e declarações com base no contexto. A maioria das principais linguagens estaticamente tipadas, como C ++ , C # e Java , são manifestamente tipadas. A inferência de tipo completa tem sido tradicionalmente associada a linguagens menos convencionais, como Haskell e ML . No entanto, muitas linguagens manifestamente tipadas oferecem suporte à inferência de tipo parcial; por exemplo, C ++ , Java e C # todos inferem tipos em certos casos limitados. Além disso, algumas linguagens de programação permitem que alguns tipos sejam convertidos automaticamente em outros tipos; por exemplo, um int pode ser usado onde o programa espera um float.

A tipagem dinâmica , também chamada de tipagem latente , determina a segurança de tipo das operações em tempo de execução; em outras palavras, os tipos são associados a valores de tempo de execução em vez de expressões textuais . Como ocorre com as linguagens inferidas por tipo, as linguagens digitadas dinamicamente não exigem que o programador escreva anotações de tipo explícitas nas expressões. Entre outras coisas, isso pode permitir que uma única variável se refira a valores de diferentes tipos em diferentes pontos na execução do programa. No entanto, os erros de tiponão podem ser detectados automaticamente até que uma parte do código seja realmente executada, tornando a depuração potencialmentemais difícil. Lisp , Smalltalk , Perl , Python , JavaScript e Ruby são todos exemplos de linguagens tipadas dinamicamente.

Digitação fraca e forte

A digitação fraca permite que um valor de um tipo seja tratado como outro, por exemplo, tratando uma string como um número. Isso pode ocasionalmente ser útil, mas também pode permitir que alguns tipos de falhas do programa não sejam detectadas em tempo de compilação e até mesmo em tempo de execução .

A digitação forte evita essas falhas do programa. Uma tentativa de realizar uma operação com o tipo errado de valor gera um erro. Linguagens fortemente tipadas são freqüentemente denominadas seguras de tipo ou seguras .

Uma definição alternativa para "tipo fraco" refere-se a linguagens, como Perl e JavaScript , que permitem um grande número de conversões de tipo implícitas. Em JavaScript, por exemplo, a expressão 2 * xconverte implicitamente xa um número, e esta conversão consegue mesmo se xé null, undefined, um Array, ou uma seqüência de letras. Essas conversões implícitas costumam ser úteis, mas podem mascarar erros de programação. Agora, forte e estático são geralmente considerados conceitos ortogonais, mas o uso na literatura é diferente. Alguns usam o termo fortemente tipado para significar fortemente tipado estaticamente ou, ainda mais confuso, para significar simplesmente tipado estaticamente . Assim, C foi chamado de tipagem forte e de tipagem fraca e estática.

Pode parecer estranho para alguns programadores profissionais que C possa ser "fracamente, estaticamente tipado". No entanto, observe que o uso do ponteiro genérico, o ponteiro void * , permite a conversão de ponteiros para outros ponteiros sem a necessidade de uma conversão explícita. Isso é extremamente semelhante a converter de alguma forma uma matriz de bytes para qualquer tipo de tipo de dados em C sem usar uma conversão explícita, como (int)ou (char).

Biblioteca padrão e sistema de tempo de execução

A maioria das linguagens de programação tem uma biblioteca central associada (às vezes conhecida como 'biblioteca padrão', especialmente se for incluída como parte do padrão de linguagem publicado), que é convencionalmente disponibilizada por todas as implementações da linguagem. Bibliotecas centrais geralmente incluem definições para algoritmos comumente usados, estruturas de dados e mecanismos de entrada e saída.

A linha entre uma linguagem e sua biblioteca central difere de uma linguagem para outra. Em alguns casos, os designers da linguagem podem tratar a biblioteca como uma entidade separada da linguagem. No entanto, a biblioteca central de uma linguagem é frequentemente tratada como parte da linguagem por seus usuários, e algumas especificações de linguagem até exigem que essa biblioteca seja disponibilizada em todas as implementações. Na verdade, algumas linguagens são projetadas de forma que os significados de certas construções sintáticas não possam ser descritos sem referência à biblioteca central. Por exemplo, em Java , um literal de string é definido como uma instância da java.lang.Stringclasse; da mesma forma, em Smalltalk , uma expressão de função anônima (um "bloco") constrói uma instância da BlockContextclasse da biblioteca . Por outro lado, Scheme contém vários subconjuntos coerentes que são suficientes para construir o resto da linguagem como macros de biblioteca, e assim os designers de linguagem nem se preocupam em dizer quais partes da linguagem devem ser implementadas como construções de linguagem e quais devem ser implementadas como partes de uma biblioteca.

Design e implementação

As linguagens de programação compartilham propriedades com as linguagens naturais relacionadas à sua finalidade como veículos de comunicação, tendo uma forma sintática separada de sua semântica e mostrando famílias de linguagens relacionadas que se ramificam umas das outras. Mas, como construções artificiais, eles também diferem fundamentalmente das linguagens que evoluíram com o uso. Uma diferença significativa é que uma linguagem de programação pode ser totalmente descrita e estudada em sua totalidade, uma vez que possui uma definição precisa e finita. Em contraste, as línguas naturais têm significados mutáveis ​​dados por seus usuários em diferentes comunidades. Embora as linguagens construídas também sejam linguagens artificiais projetadas desde o início com um propósito específico, elas carecem da definição semântica precisa e completa que uma linguagem de programação possui.

Muitas linguagens de programação foram projetadas do zero, alteradas para atender a novas necessidades e combinadas com outras linguagens. Muitos acabaram caindo em desuso. Embora tenha havido tentativas de projetar uma linguagem de programação "universal" que sirva a todos os propósitos, todas elas falharam em ser geralmente aceitas como preenchendo essa função. A necessidade de diversas linguagens de programação surge da diversidade de contextos nos quais as linguagens são usadas:

  • Os programas variam de minúsculos scripts escritos por amadores individuais a enormes sistemas escritos por centenas de programadores .
  • Os programadores variam em experiência, de novatos que precisam de simplicidade acima de tudo a especialistas que podem se sentir confortáveis ​​com uma complexidade considerável.
  • Os programas devem equilibrar velocidade, tamanho e simplicidade em sistemas que variam de microcontroladores a supercomputadores .
  • Os programas podem ser escritos uma vez e não mudar por gerações ou podem sofrer modificações contínuas.
  • Os programadores podem simplesmente diferir em seus gostos: eles podem estar acostumados a discutir problemas e expressá-los em uma linguagem específica.

Uma tendência comum no desenvolvimento de linguagens de programação tem sido adicionar mais capacidade de resolver problemas usando um nível mais alto de abstração . As primeiras linguagens de programação estavam intimamente ligadas ao hardware subjacente do computador. À medida que novas linguagens de programação foram desenvolvidas, recursos foram adicionados que permitem aos programadores expressar ideias que são mais remotas da simples tradução em instruções de hardware subjacentes. Como os programadores estão menos presos à complexidade do computador, seus programas podem fazer mais computação com menos esforço do programador. Isso permite que eles escrevam mais funcionalidades por unidade de tempo.

A programação em linguagem natural foi proposta como uma forma de eliminar a necessidade de uma linguagem especializada para programação. No entanto, esse objetivo permanece distante e seus benefícios estão abertos para debate. Edsger W. Dijkstra assumiu a posição de que o uso de uma linguagem formal é essencial para evitar a introdução de construções sem sentido e descartou a programação em linguagem natural como "tola". Alan Perlis também rejeitou a ideia. Abordagens híbridas foram adotadas em inglês estruturado e SQL .

Os designers e usuários de uma linguagem devem construir uma série de artefatos que governam e permitem a prática da programação. Os mais importantes desses artefatos são a especificação e implementação da linguagem .

Especificação

A especificação de uma linguagem de programação é um artefato que os usuários da linguagem e os implementadores podem usar para concordar se uma parte do código-fonte é um programa válido nessa linguagem e, em caso afirmativo, qual deve ser o seu comportamento.

Uma especificação de linguagem de programação pode assumir várias formas, incluindo as seguintes:

  • Uma definição explícita da sintaxe, semântica estática e semântica de execução da linguagem. Enquanto a sintaxe é comumente especificada usando uma gramática formal, as definições semânticas podem ser escritas em linguagem natural (por exemplo, como na linguagem C ), ou uma semântica formal (por exemplo, como em ML padrão e especificações de esquema ).
  • Uma descrição do comportamento de um tradutor para a linguagem (por exemplo, as especificações C ++ e Fortran ). A sintaxe e a semântica da linguagem devem ser inferidas desta descrição, que pode ser escrita em linguagem natural ou formal.
  • Uma referência ou implementação de modelo , às vezes escrita na linguagem especificada (por exemplo, Prolog ou ANSI REXX ). A sintaxe e a semântica da linguagem são explícitas no comportamento da implementação de referência.

Implementação

Uma implementação de uma linguagem de programação fornece uma maneira de escrever programas nessa linguagem e executá-los em uma ou mais configurações de hardware e software. Existem, de maneira geral, duas abordagens para a implementação da linguagem de programação: compilação e interpretação . Geralmente é possível implementar uma linguagem usando qualquer uma das técnicas.

A saída de um compilador pode ser executada por hardware ou por um programa chamado interpretador. Em algumas implementações que fazem uso da abordagem do interpretador, não há limite distinto entre compilar e interpretar. Por exemplo, algumas implementações do BASIC compilam e executam o código-fonte uma linha por vez.

Os programas executados diretamente no hardware geralmente são executados muito mais rápido do que aqueles interpretados no software.

Uma técnica para melhorar o desempenho de programas interpretados é a compilação just-in-time . Aqui a máquina virtual , pouco antes da execução, traduz os blocos de bytecode que serão usados ​​em código de máquina, para execução direta no hardware.

Linguagens proprietárias

Embora a maioria das linguagens de programação mais comumente usadas tenham especificações e implementações totalmente abertas, muitas linguagens de programação existem apenas como linguagens de programação proprietárias, com a implementação disponível apenas de um único fornecedor, que pode alegar que tal linguagem proprietária é sua propriedade intelectual. Linguagens de programação proprietárias são comumente linguagens específicas de domínio ou linguagens de script internas para um único produto; algumas linguagens proprietárias são usadas apenas internamente em um fornecedor, enquanto outras estão disponíveis para usuários externos.

Algumas linguagens de programação existem na fronteira entre proprietárias e abertas; por exemplo, Oracle Corporation afirma direitos de propriedade sobre alguns aspectos da linguagem de programação Java e Microsoft 's C # linguagem de programação, que tem implementações abertas da maioria das partes do sistema, também tem Common Language Runtime (CLR) como um ambiente fechado.

Muitas linguagens proprietárias são amplamente utilizadas, apesar de sua natureza proprietária; exemplos incluem MATLAB , VBScript e Wolfram Language . Alguns idiomas podem fazer a transição de fechado para aberto; por exemplo, Erlang era originalmente uma linguagem de programação interna da Ericsson.

Usar

Milhares de diferentes linguagens de programação foram criadas, principalmente na área de computação. Projetos de software individuais geralmente usam cinco linguagens de programação ou mais.

As linguagens de programação diferem da maioria das outras formas de expressão humana porque exigem um grau maior de precisão e integridade. Ao usar uma linguagem natural para se comunicar com outras pessoas, os autores e falantes humanos podem ser ambíguos e cometer pequenos erros e ainda esperar que sua intenção seja compreendida. No entanto, falando figurativamente, os computadores "fazem exatamente o que lhes é dito para fazer" e não podem "entender" que código o programador pretendia escrever. A combinação da definição de linguagem, um programa e as entradas do programa deve especificar totalmente o comportamento externo que ocorre quando o programa é executado, dentro do domínio de controle desse programa. Por outro lado, ideias sobre um algoritmo podem ser comunicadas a humanos sem a precisão necessária para execução por meio do pseudocódigo , que intercala a linguagem natural com o código escrito em uma linguagem de programação.

Uma linguagem de programação fornece um mecanismo estruturado para definir partes de dados e as operações ou transformações que podem ser realizadas automaticamente nesses dados. Um programador usa as abstrações presentes na linguagem para representar os conceitos envolvidos em uma computação. Esses conceitos são representados como uma coleção dos elementos mais simples disponíveis (chamados primitivos ). Programação é o processo pelo qual os programadores combinam essas primitivas para compor novos programas ou adaptar os existentes a novos usos ou a um ambiente em mudança.

Os programas para um computador podem ser executados em um processo em lote sem interação humana, ou um usuário pode digitar comandos em uma sessão interativa de um intérprete . Neste caso, os "comandos" são simplesmente programas, cuja execução é encadeada. Quando uma linguagem pode executar seus comandos por meio de um interpretador (como um shell Unix ou outra interface de linha de comando ), sem compilar, é chamada de linguagem de script .

Medindo o uso da linguagem

Determinar qual é a linguagem de programação mais amplamente usada é difícil, pois a definição de uso varia de acordo com o contexto. Uma linguagem pode ocupar o maior número de horas de programação, uma outra pode ter mais linhas de código e uma terceira pode consumir mais tempo da CPU. Alguns idiomas são muito populares para determinados tipos de aplicativos. Por exemplo, COBOL ainda é forte no data center corporativo, geralmente em grandes mainframes ; Fortran em aplicações científicas e de engenharia; Ada em aplicações aeroespaciais, de transporte, militares, em tempo real e embarcadas; e C em aplicativos e sistemas operacionais incorporados. Outras linguagens são usadas regularmente para escrever muitos tipos diferentes de aplicativos.

Vários métodos de medir a popularidade da linguagem, cada um sujeito a um viés diferente sobre o que é medido, foram propostos:

  • contando o número de anúncios de emprego que mencionam o idioma
  • o número de livros vendidos que ensinam ou descrevem o idioma
  • estimativas do número de linhas de código existentes escritas na linguagem - o que pode subestimar linguagens que não costumam ser encontradas em pesquisas públicas
  • contagens de referências de idioma (ou seja, para o nome do idioma) encontradas usando um mecanismo de pesquisa na web.

Combinando e calculando a média de informações de vários sites da internet, stackify.com relatou as dez linguagens de programação mais populares como (em ordem decrescente por popularidade geral): Java , C , C ++ , Python , C # , JavaScript , VB .NET , R , PHP e MATLAB .

Dialetos, sabores e implementações

Um dialeto de uma linguagem de programação ou de uma linguagem de troca de dados é uma variação (relativamente pequena) ou extensão da linguagem que não muda sua natureza intrínseca. Com linguagens como Scheme e Forth , os padrões podem ser considerados insuficientes, inadequados ou ilegítimos pelos implementadores, então muitas vezes eles se desviam do padrão, criando um novo dialeto . Em outros casos, um dialeto é criado para uso em um idioma específico do domínio , geralmente um subconjunto. No mundo Lisp , a maioria das linguagens que usam sintaxe de expressão S básica e semântica semelhante a Lisp são consideradas dialetos Lisp, embora variem muito, como, digamos, Racket e Clojure . Como é comum que uma linguagem tenha vários dialetos, pode ser muito difícil para um programador inexperiente encontrar a documentação correta. A linguagem de programação BASIC tem muitos dialetos .

A explosão dos dialetos Forth levou ao ditado "Se você viu um Forth ... você viu um Forth."

Taxonomias

Não existe um esquema de classificação abrangente para linguagens de programação. Uma determinada linguagem de programação geralmente não possui uma única linguagem ancestral. As línguas surgem comumente pela combinação de elementos de várias línguas predecessoras com novas ideias em circulação na época. As ideias que se originam em um idioma se difundirão por uma família de idiomas relacionados e, então, saltarão repentinamente através das lacunas familiares para aparecer em uma família totalmente diferente.

A tarefa é ainda mais complicada pelo fato de que os idiomas podem ser classificados em vários eixos. Por exemplo, Java é uma linguagem orientada a objetos (porque incentiva a organização orientada a objetos) e uma linguagem concorrente (porque contém construções integradas para executar vários threads em paralelo). Python é uma linguagem de script orientada a objetos .

Em linhas gerais, as linguagens de programação se dividem em paradigmas de programação e uma classificação por domínio de uso pretendido, com linguagens de programação de propósito geral distintas das linguagens de programação de domínio específico . Tradicionalmente, as linguagens de programação têm sido consideradas como descrevendo a computação em termos de sentenças imperativas, ou seja, emissão de comandos. Geralmente são chamadas de linguagens de programação imperativas . Uma grande quantidade de pesquisas em linguagens de programação tem como objetivo confundir a distinção entre um programa como um conjunto de instruções e um programa como uma afirmação sobre a resposta desejada, que é a principal característica da programação declarativa . Paradigmas mais refinados incluem programação procedural , programação orientada a objetos , programação funcional e programação lógica ; algumas linguagens são híbridos de paradigmas ou multiparadigmáticos. Uma linguagem assembly não é tanto um paradigma quanto um modelo direto de uma arquitetura de máquina subjacente. Por propósito, as linguagens de programação podem ser consideradas de propósito geral, linguagens de programação de sistema , linguagens de script, linguagens de domínio específico ou linguagens concorrentes / distribuídas (ou uma combinação delas). Algumas linguagens de uso geral foram desenvolvidas principalmente com objetivos educacionais.

Uma linguagem de programação também pode ser classificada por fatores não relacionados ao paradigma de programação. Por exemplo, a maioria das linguagens de programação usa palavras-chave do idioma inglês , enquanto uma minoria não . Outras línguas podem ser classificadas como deliberadamente esotéricas ou não.

Veja também

Referências

Leitura adicional

links externos