Quais as vantagens é desvantagens de uma linguagem interpretada sobre uma compilada?

Terminologia correta

Primeiro, não existe isso de linguagem interpretada ou compilada. Salvo alguma característica própria ou especificação, todas podem ser interpretadas e/ou compiladas. Existem implementações de linguagens que podem interpretar ou compilar o código escrito naquela linguagem.

Claro que usar estes termos da pergunta não pode ser considerado totalmente errado já que todo mundo entende o seu significado, mas estritamente falando é errado.

Mesmo assim nestes momentos sentimos vergonha alheia por ter os verbetes na Wikipedia. E eles tentam explicar o inexplicável. E o fazem de forma bem equivocada. Provavelmente fazendo muito leigo achar que aquilo é verdadeiro. Uma análise mais detalhada indica que as definições propostas lá inviabilizariam outras definições consagradas. Não está totalmente errado, mas eles possuem imprecisões importantes. A versão em português é pior.

Resumo

A interpretação ocorre quando o uso (comumente a execução) do código se dá junto à análise do mesmo.

A compilação é o processo de análise e possivelmente transformação do código fonte em código alvo, ou seja, o uso (execução, por exemplo) se dá em processo separado posterior, ainda que não tão posterior assim.

Então aplicações que rodam interpretadas precisam do código fonte enquanto que as compiladas só precisam do código alvo para funcionar.

Interpretação

A interpretação ocorre em cima do código fonte da aplicação escrita. Existem várias formas de proceder a interpretação, que é a análise do código no momento da execução. Pode ser feito em partes pequenas (linhas, por exemplo) ou em partes maiores, funções ou arquivos.

Neste processo a análise do código é feita todas as vezes que ele precisa executar, e os erros só são detectados durante a execução. Esta é uma diferença fundamental.

Interpretador

Obviamente que para executar código interpretado é necessário um software interpretador. E, pasmem, ele pode ser interpretado também, ainda que não seja comum.

Esse software interpretador controla o fluxo do trabalho da interpretação e garante a execução do que for necessário.

É comum a interpretação envolver um passo de compilação não só para a análise mas também para a transformação do código. Isto pode ocorrer por completo ou em partes. Mas ela ocorrerá sob demanda e ela ocorrerá por discrição do interpretador. Pra falar a verdade não é fácil fazer uma interpretação sem alguma forma de compilação, mesmo que rudimentar.

Em alguns casos esta compilação costuma ser chamada de just-in-time. Mas é importante diferenciar da compilação tradicional que tem uma função diferente. Eu prefiro considerar isso mais uma compilação que uma interpretação.

Área nebulosa

É importante entender que a interpretação envolve um processo de compilação que pode até mesmo transformar um código fonte em outro código alvo. A grande diferença é que após esta compilação já existe uma ação ocorrendo. Então mesmo que ocorra uma transformação, erros só são detectados no momento da execução ou alguns instantes antes dela efetivamente se iniciar, mas dentro do mesmo processo.

Há quem ache que se existe este processo de compilação do fonte em código alvo, especialmente se for nativo à máquina que esta suportando a execução, imediatamente anterior à execução faria isto ser considerado um código compilado. Sim, o código alvo é compilado, mas ele é transparente ao processo todo, isto é discricional ao interpretador. E esta compilação não pode se dedicar a otimizar o código sob pena de criar um custo maior que o ganho.

Empacotamento

É possível encapsular código fonte em um arquivo único, possivelmente dentro de um executável, podendo compactá-lo e até mesmo criptografá-lo, mas ainda assim ter o processo de interpretação.

Vantagem

A maior e mais perceptível vantagem da interpretação é a facilidade e rapidez para iniciar a execução do código já escrito.

Algumas pessoas citam outras vantagens desta forma de execução de códigos, mas que na verdade a vantagem é colateral ou apenas relacionada, ou seja, é comum ter a vantagem em "linguagens interpretadas" mas na verdade é uma coincidência e a vantagem não ocorre pela interpretação em si. Outros casos citados são por desconhecimento que a forma compilada também pode ter as mesmas vantagens. Se uma linguagem normalmente compilada não fornece a vantagem, é um problema dela e não do método de execução.

Uma destas supostas vantagens citadas costuma ser poder rodar em várias plataformas. Códigos compilados também podem se não forem compilados para código nativo diretamente. E códigos interpretados por interpretadores que só estão disponíveis para uma plataforma não tem esta flexibilidade. A vantagem não é uma propriedade da forma de execução. Então pode-se falar em tendência, mas não uma garantia.

Do ponto de vista de implementação da linguagem é mais fácil fazer um interpretador, especialmente linguagens dinâmicas. Mas não acho que isto interesse para a maioria das pessoas, parte da facilidade é porque não se espera muito de linguagens que são pensadas mais para funcionarem de forma interpretada.

Compilação

A compilação tradicional considera partes maiores de código sempre, é preciso entender o todo do código. Não precisa ser feita em toda a aplicação mas em tudo o que é necessário em determinada parte do código.

A análise é feita de forma semelhante ao da interpretação, tanto que, muitas vezes o processo de interpretação no fundo é feito por um compilador. É claro que o funcionamento deste compilador é um pouco diferente no interpretador. Mas a análise léxica, sintática e semântica que todo compilador faz também é necessária no interpretador.

A grande diferença entre ambos é a forma como o resultado é gerado. A interpretação executa o código analisado. A compilação gera um outro código que será posteriormente usado (executado) por um ambiente que entenda o seu funcionamento. Pode ser uma máquina virtual ou uma máquina real.

Execução

Então códigos compilados (em um código alvo) costumam rodar em cima de uma aplicação que simula uma máquina ou um sistema operacional, ou se o código for considerado nativo em cima de um sistema operacional real. Embora existam casos que códigos compilados gerem binários capazes de executar em uma máquina por conta própria, o mais comum é precisar de um software que controle a sua execução no geral (mas não controle as instruções), assim como códigos interpretados. A diferença é a forma como a execução ocorre.

Códigos compilados para executáveis nativos podem ter seu código passado diretamente ao processador. Executáveis com bytecodes intermediários podem ser compilados para código nativo ou executado através de uma decodificação e execução em laços (loops) da máquina virtual, o que é parecido com uma intepretação.

Compilações costumam gerar códigos de máquina nativos ou de ambientes virtuais, mas não necessariamente. Eles podem gerar outros códigos fonte ou outras formas que eles podem ser usados posteriormente. Há quem diga que só há código compilado quando ele é nativo.

Existem casos em que o processo de compilação gera um código intermediário que depois poderá ser compilado novamente. A segunda compilação normalmente é chamada de just-in-time compilation feita por um JITter. Mas esta compilação é diferente.

A compilação não precisa necessariamente gerar nada, ela pode ser feita apenas como verificação ou pode gerar um código que não será executado.

Empacotamento

Após a compilação existem casos onde se faz a linkedição que gera um arquivo executável com tudo o que precisa para executar e em um formato suportado por algum sistema operacional. Mas isso não é verdade em vários casos que utilizam máquinas virtuais.

Vantagens

Uma vantagem clara do uso de códigos compilados é que uma parte considerável dos erros de programação podem ser evitados no processo de compilação e nunca chegam para a execução.

Códigos compilados são mais fáceis de proteger a propriedade intelectual, especialmente quando se distribui apenas o código nativo. Mas é possível fazer o mesmo com códigos a serem interpretados, depende de implementação. Proteção completa não existe em nenhum caso, apenas a facilidade maior é uma vantagem.

Outra vantagem é que códigos compilados costumam executar mais rapidamente, já que a análise não precisa ser feita durante a execução, além do que, por analisar o código de forma integral, pode fazer otimizações. Algumas destas otimizações demoram para serem realizadas pelo compilador, mas como este trabalho de otimização não atrasará a execução ele pode ser feito confortável e agressivamente.

Velocidade

Costuma haver uma confusão com o ganho de velocidade de algumas linguagens. Embora as duas melhorias citadas acima sejam importantes para dar velocidade para aplicações, muitas vezes um fator muito importante é que "linguagens compiladas" tendem ter características próprias que ajudam a velocidade por si só.

Por exemplo elas costumam usar tipagem estática e não dinâmica, como é comum nas linguagens interpretadas. Claro que o oposto pode ocorrer, mas como é comum haver uma relação entre esses tipos de linguagens, há a confusão entre os mais leigos no assunto.

Outro ponto importante é que linguagens que oferecem acesso mais baixo nível dão melhor atenção a certos detalhes e melhor controle sobre o código, e portanto oferecem melhor performance, costumam ser compiladas, mas isto é uma coincidência não uma característica inerente.

Algumas pessoas vão dizer que a compilação gera código nativo e por ele rodar diretamente há ganho de performance. Isto é verdade, mas é um efeito colateral. Assembly não é compilado (é montado, como o próprio nome diz, tá, é verdade que alguns até são compilados) e gera código nativo que é rápido. Não é o processo da compilação que faz o código executar mais rápido, neste caso.

Isto costuma ser verdade, no entanto é possível executar códigos interpretados mais rapidamente por ele oferecer melhor contexto, apesar que não é fácil, não acontece sempre.

Então não é possível executar um código em Python mais rápido que um mesmo código escrito em C++, se ambos forem bem escritos e não for algo feito especificamente para mostrar um corner case que não tem relevância no mundo real (eu sei que alguém vai querer mostrar que tem algum jeito maluco, muito específico que Python consegue ser mais rápido). Mesmo que o código Python seja compilado (e isto é possível).

Assunto polêmico

Na verdade nunca achei informação que cravasse uma definição clara sobre isso. Já vi definições diferentes desta, algumas colocando mais critérios para definir o que é uma coisa ou outra. Algumas fazendo afirmações do que é cada um que inviabilizaria dar definições claras de quando uma aplicação é compilada ou interpretada.

Se você considerar que gerar código nativo é que define que um código está rodando compilado, inviabiliza a descrição do termo como ele é conhecido universalmente. A compilação não pode se restringir à geração de código nativo. E o simples fato de ter um código nativo não significa que o processo para chegar lá não tenha uma interpretação. Alguns dirão que há casos que não é compilação e sim transpilação, que no fundo sempre tem uma parte de compilação.

Existe ainda o processo híbrido onde um código é compilado mas o resultado é algo que precisa ser interpretado. Lembre-se que a compilação pode gerar qualquer outro código em qualquer linguagem que depois precise ser compilada ou interpretada.

JavaScript

JavaScript é interpretada ou compilada? Nem estou falando do Rhino ou JScript que são obviamente compilados e depois executados em cima da JVM e CLR, respectivamente. Falo do código que roda nos navegadores.

Na minha visão é interpretada. Hoje todos os bons navegadores compilam o código fonte em código nativo, de uma forma ou de outra, mas precisa fazer a análise do código fonte, que obviamente é necessário, todas as vezes antes de executar, e os erros serão verificados logo no momento imediato ao da execução. Pra mim isto é interpretação. A transformação em código nativo é só uma otimização.

Em geral os engines dos navegadores costumam executar códigos mais rapidamente que estas implementações que compilam o código JS.

Alguém pode dizer: e se os navegadores fizerem cache do código nativo? Talvez já o façam, não sei como os engines modernos estão operando. Eu acho que o cache aí é apenas uma estratégia de otimização do interpretador. O código nativo pode desaparecer, ficar invalidado, etc. Ele não é o foco e é opcional.

Mas a execução é compilada, então usar este termo não é exatamente errado. Mas pra mim o código da sua aplicação, estritamente falando, passa por um processo de interpretação.

TypeScript

É compilada ou interpretada?

Tem até um compilador, então não pode ter dúvida. TypeScript compila para JavaScript.

O fato da linguagem alvo ser interpretada é outro problema. E é por circunstâncias. Um dia pode não ser mais (provavelmente não será), sem afetar a TypeScript.

Os erros possíveis são verificados pelo compilador, a análise da linguagem é feita toda em processo isolado e bem anterior à execução, e algumas otimizações possíveis são feitas na compilação.

Lua

Esta é uma linguagem que permite interpretar o código fonte (embora tenha um processo de compilação interno), permite executar um bytecode próprio que foi gerado pelo compilador e pode ser interpretado para código nativo com a implementação (ou dialeto?) LuaJIT (O que é um JITter).

LuaJIT é um caso curioso porque executa de forma interpretada mais rápido que Lua compilado. Foi criado para isto mesmo. Quem diria que um código interpretado pode ser mais rápido que um compilado. E estamos falando da mesma linguagem. Seria injusto comparar linguagens diferentes porque os ganhos de velocidade poderiam vir de outras características da linguagem.

Note que LuaJIT preferiu usar o código fonte e não o bytecode compilado porque isto daria melhor performance. E um dos motivos é que certas partes ficam mais lentas se elas tiveram que ser transformadas em código nativo.

Java e C#

Estas linguagens compilam para um bytecode.

A maiorias das pessoas as consideram como "linguagens compiladas" (não vou entrar no mérito que elas podem alternativamente ser interpretadas também) mas há quem diga que são interpretadas já que precisa de um passo seguinte para executar.

Eu considero estas linguagens compiladas mesmo. Elas geram um JVM bytecode ou um CIL bytecode. As pessoas dizem que eles são interpretados. Bom, eu vejo um erro aí. As pessoas estão falando que estas duas linguagens intermediárias citadas neste parágrafo são interpretadas. Elas não estão mais falando de Java e C#.

Teve uma época que a linguagem JVM bytecode era decodificada pela máquina virtual e depois executada. Pra mim isto nem era interpretação, embora informalmente eu até digo que é interpretado. Decodificação é um processo muito mais simples. Mas até aceito neste caso. O JVM atual ou o CIL bytecode também é compilado para código nativo.

Erros de programação que eram possíveis já foram detectados, otimizações pesadas já foram feitas e você não precisa de um código fonte original e que precisa de um processo de parsing. Pram mim isto não é interpretação.

Estas linguagens possuem compiladores. Se elas são interpretadas, estas ferramentas estão com nome errado?

E quando está rodando o REPL do C#, por exemplo? Tem um compilador (.NET Compiler Platform) que trabalha para o interpretador, mas claramente há um processo de interpretação.

E essas linguagens podem rodar, e até rodam de forma totalmente nativa em certas circunstâncias

C e C++

Ah, essas são compiladas com certeza! Ou não? Já viu o Cint ou o Ch ou outros?

Conclusão

Estão aí definições, comparações, etc. Mas nem conseguimos definir claramente quando um código está sendo interpretado ou compilado. Ou seja, isto tem importância limitada. Especialmente porque a interpretação é enormemente beneficiada pela compilação e códigos compilados podem eventualmente se comportar como códigos interpretados, aplicando-se as devidas técnicas.

Se levar ao pé da letra algumas definições encontradas por aí, praticamente não existem mais interpretadores.

Referências

  • Duas respostas excelentes, uma de um bom desenvolvedor que entende do assunto e outra deste meia-boca que vos fala. É praticamente uma pergunta duplicata.
  • Pergunta aqui do site sobre o JS.
  • Linguagens compiladas.
  • Linguagens interpretadas (não confie totalmente).

Coloquei no GitHub para referência futura.

Quais as vantagens é desvantagens de uma linguagem interpretada é de uma linguagem compilada?

Vantagens das linguagens compiladas Os programas compilados em código de máquina nativo tendem a ser mais rápidos que o código interpretado. Isso ocorre porque o processo de traduzir o código em tempo de execução aumenta o tempo do processo, podendo fazer com que o programa seja, em geral, mais lento.

Quais as vantagens é desvantagens do interpretador?

Consomem menos memória. Desvantagem: Execução é mais lenta do programa. Necessita sempre ter lido o código original para ser executado.

Qual a vantagem do interpretador sobre o compilador?

O interpretador ao contrário do compilador roda o código-fonte escrito como sendo o código objeto, ele traduz o programa linha a linha, o programa vai sendo utilizado na medida em que vai sendo traduzido. Cada execução do programa precisa ser novamente traduzido e interpretado.

Qual a diferença entre compilação é interpretação?

Ao utilizar o método de compilação, o compilador irá ler o código, fazer todas as análises sintáticas e demais processos, para, por fim, gerar um arquivo código-objeto ou um arquivo executável. Já na interpretação, nenhum arquivo ou código é gerado, e sim uma tradução instantânea, em tempo de execução.