Esempi di quando useremo il linguaggio interpretato rispetto al linguaggio compilato?


11

Comprendo le differenze tra le lingue interpretate e compilate, ma se qualcuno potesse fornire alcuni esempi di situazioni in cui è probabile che si utilizzino lingue interpretate su lingue compilate, nonché situazioni in cui è probabile che si utilizzino lingue compilate su lingue interpretate, sarebbe essere davvero utile.

Risposte:


11

Per quanto ne so, non esiste una "lingua" interpretata o una "lingua" compilata.

Le lingue specificano la sintassi e il significato delle parole chiave del codice, dei costrutti di flusso e di varie altre cose, ma non sono a conoscenza di alcuna lingua che specifichi se deve essere compilato o interpretato o meno nelle specifiche della lingua.

Ora, se la tua domanda è quando usi un compilatore di lingue rispetto a un interprete di lingue, si riduce davvero ai pro / contro del compilatore rispetto all'interprete e allo scopo del progetto.

Ad esempio, è possibile utilizzare il compilatore JRuby per una più facile integrazione con le librerie Java invece dell'interprete ruby ​​MRI. Probabilmente ci sono anche ragioni per usare l'interprete ruby ​​di risonanza magnetica su JRuby, ma non ho familiarità con la lingua e non posso parlarne.

Benefici stimati degli interpreti:

  • Nessuna compilazione significa che il tempo dalla modifica del codice al test dell'app può essere ridotto
  • Non c'è bisogno di generare binari per architetture multiple perché l'interprete gestirà l'architettura astrazione (anche se si potrebbe essere necessario ancora preoccuparsi della movimentazione intero dimensioni in modo corretto, non solo la distribuzione binaria script)

Benefici stimati dei compilatori:

  • Il codice nativo compilato non ha il sovraccarico di un interprete ed è quindi generalmente più efficiente in termini di tempo e spazio
  • L'interoperabilità è generalmente migliore, l'unico modo per l'interoperabilità in-proc con gli script è tramite un interprete anziché un FFI standard
  • Capacità di supportare architetture per le quali l'interprete non è stato compilato (come i sistemi integrati)

Tuttavia, scommetterei nel 90% dei casi che va qualcosa di più simile a questo: voglio scrivere questo software in blub perché lo conosco bene e dovrebbe fare un buon lavoro. Userò l'interprete blub (o compilatore) perché è il metodo canonico generalmente accettato per scrivere software in blub.

Quindi TL; DR è fondamentalmente un confronto caso per caso degli interpreti rispetto ai compilatori per il tuo caso d'uso specifico.

Inoltre, FFI: Foreign Function Interface, in altre parole interfaccia per l'interoperabilità con altre lingue. Altre letture su Wikipedia


2
Per quanto ne so, alcuni linguaggi di scripting per sistemi operativi come ksh per UNIX non possono essere compilati.
NoChance,

@delnan, il mio punto è che non può essere compilato attraverso un software commerciale o gratuito di cui io sia a conoscenza, non che non possa essere compilato per motivi tecnici.
NoChance,

3
@EmmadKareem Non esiste una cosa come "impossibile compilare". Scrivi un programma che legge un programma in lingua Li e genera un programma equivalente in lingua La. Questo è un compilatore un compilatore. Esito a invocare l'argomento completezza turing in quanto si tratta in pratica di un'aringa rossa, ma ogni programma alla fine si trasforma in una sequenza di istruzioni del codice macchina. Se tutto il resto fallisce, srotolare il ciclo dell'interprete (e semplificare il codice risultante per rimuovere le parti non più necessarie). Se l'interprete è scritto in una lingua senza interpreti, ripeti finché non colpisci qualcosa con un compilatore.

1
(Ho redatto il mio commento per esprimerlo meglio, ma apparentemente ho agito troppo tardi.) @EmmadKareem Sì, ovviamente alcune lingue non sono mai state implementate tramite un compilatore. Ma non riesco a vedere quanto sia rilevante. È sempre possibile e fattibile farlo, e può essere fatto in qualsiasi momento con un certo sforzo. Questa è una conseguenza del punto principale, ovvero che una lingua non è né intrinsecamente compilata né interpretata, e può essere implementata in entrambi i modi. E in una miriade di altri modi (beh, probabilmente varianti e remix minori), comunque.

2
@EmmadKareem se lo desideri, puoi prendere le specifiche del linguaggio ksh e scrivere un compilatore che lo legge e genera un file binario nativo. Il linguaggio in fase di compilazione o interpretazione non è nella definizione di una lingua è il mio punto qui.
Jimmy Hoffa,

8

Un punto importante qui è che molte implementazioni linguistiche in realtà fanno una sorta di ibrido di entrambi. Molte lingue comunemente usate oggi funzionano compilando un programma in un formato intermedio come bytecode e quindi eseguendolo in un interprete. Ecco come vengono implementati Java, C #, Python, Ruby e Lua. In realtà, questo è probabilmente il modo in cui viene implementata la maggior parte del linguaggio in uso oggi. Quindi, il fatto è che il linguaggio oggi interpreta e compila il loro codice. Alcune di queste lingue hanno un compilatore JIT aggiuntivo per convertire il bytecode in codice nativo per l'esecuzione.

A mio avviso, dovremmo smettere di parlare di linguaggi interpretati e compilati perché non sono più categorie utili per distinguere le complessità delle attuali implementazioni linguistiche.

Quando chiedi dei meriti delle lingue interpretate e compilate, probabilmente intendi qualcos'altro. Potresti chiedere il merito della tipizzazione statica / dinamica, i vantaggi della distribuzione di eseguibili nativi, i vantaggi relativi della compilazione JIT e AOT. Questi sono tutti problemi che si confondono con l'interpretazione / compilazione ma sono diversi.


2

Prima di tutto, un linguaggio di programmazione può essere sia interpretato che compilato. L'interpretazione e la compilazione sono solo metodi per generare codice eseguibile dal codice sorgente. Con un interprete il codice sorgente viene letto e interpretato da un interprete che quindi esegue il codice mentre lo interpreta. D'altra parte un compilatore legge il codice sorgente e genera un file binario eseguibile dal codice sorgente, in modo che il programma possa essere eseguito in modo indipendente come processo separato.

Ora, prima che qualcuno si chieda ... Sì, è possibile interpretare C / C ++ / C # / Java e sì, è possibile compilare gli script JavaScript e Bash. Se ci sono interpreti o compilatori funzionanti per queste lingue è un'altra domanda però.

Ora per rispondere effettivamente alla domanda quando useremo "linguaggio interpretato" su "linguaggio compilato". La domanda in sé è alquanto confusa, ma presumo significhi quando preferire l'interpretazione alla compilazione. Uno degli aspetti negativi della compilazione è che genera un overhead a causa del processo di compilazione: il codice sorgente deve essere compilato in codice macchina eseguibile, quindi non è adatto per attività che richiedono un ritardo minimo quando si richiama il codice sorgente per eseguire un programma. D'altra parte il codice sorgente compilato è quasi sempre più veloce del codice sorgente interpretato equivalente a causa del sovraccarico causato dall'interpretazione del codice. Gli interpreti invece possono invocare ed eseguire il codice sorgente con pochissime spese di invocazione, ma a scapito delle prestazioni di runtime.

Alla fine è quasi impossibile menzionare casi d'uso definiti quando preferire uno dopo l'altro, ma per esempio un caso (a mio avviso molto poco realistico) sarebbe quando il codice sorgente del programma cambia dinamicamente tra le invocazioni del programma e anche l'overhead della compilazione è alto per essere una scelta praticabile. In tal caso sarebbe probabilmente preferibile interpretare il codice sorgente anziché compilare.

Tuttavia, c'è qualcosa che può essere considerato un esempio reale: nascondere il codice sorgente al momento della distribuzione. Con nativamentecodice compilato lo sviluppatore distribuisce il codice macine eseguibile del programma e dei dati. Con il codice interpretato deve essere distribuito il codice sorgente stesso che può quindi essere ispezionato e retroingegnerizzato con molto meno sforzo di quello che è il reverse engineering del codice macchina nativo. Un'eccezione a ciò è rappresentata da linguaggi come C # e Java che vengono compilati in linguaggio / bytecode immediati (MSIL per C # e bytecode Java per Java) che vengono quindi distribuiti e compilati "just in time" in fase di esecuzione, un po 'come fa un interprete. Tuttavia, esistono i cosiddetti decompilatori per MSIL e Java Bytecode che possono ricostruire il codice sorgente originale con una precisione relativamente buona e come tale retroingegnerizzazione di tali prodotti è molto più banale dei prodotti di retroingegnerizzazione che sono distribuiti in codice macchina nativo.


1
Fai buoni punti, ma essendo il pedante che sono, metto in discussione alcune frasi (entrambe riferite al terzo paragrafo): 1. Un interprete non compila. 2. È immaginabile (sebbene queste condizioni siano rare) che un compilatore non ottimizzante non valido venga battuto da un interprete altamente ottimizzato (in particolare basato sul bytecode). Questo vale doppiamente se conti i compilatori JIT come interpreti (cosa che preferisco non fare, ma alcune persone lo fanno).

@delnan Forse è scritto male, non sono un madrelingua inglese. Tuttavia, per quanto ne so, il terzo paragrafo non implica che un interprete compilerebbe. Per il secondo punto, ho sottolineato la parola equivalente all'enfasi somiglianza del codice compilato e interpretato per escludere i casi di compilatore scadente rispetto a un interprete ad alte prestazioni, forse non ero chiaro con esso, tuttavia non lo vedo ragionevole concentrarsi sulla spiegazione di casi così estremi in quanto non contribuisce in alcun modo al punto che viene sottolineato tra le differenze nell'esecuzione del codice sorgente mediante la compilazione o l'interpretazione
zxcdw

Scusa, non importa il primo punto, ho letto male qualcosa. Colpa mia. Per quanto riguarda il secondo punto: ho preso "equivalente" per riferirmi al codice che viene interpretato o compilato (e confrontare un compilatore e un interprete non ha molto senso, poiché fanno cose fondamentalmente diverse). Non credo che si dovrebbe perdere tempo in dettaglio i casi stravaganti come il mio esempio, ma io preferirei cadere il "sempre" a favore di un fraseggio che spiega il motivo per cui si può essere più veloce, in primo luogo: No interprete in testa [che dovrebbe essere definito IMHO] e l'opportunità di eseguire ottimizzazioni prima del runtime.

1

Posso pensare ai seguenti scenari quando useresti un linguaggio interpretato :

  • Dove non esiste un compilatore, come gli script di shell Linux / Unix .
  • Script veloci e sporchi che risolvono un piccolo problema
  • Linguaggi che semplificano la scrittura di pagine HTML dinamiche e sono generalmente interpretati come JSP (Tomcat lo compila in un server precedente per l'esecuzione), PHP, ASP ecc.

Posso pensare ai seguenti scenari quando vuoi compilare il tuo codice:

  • Devi distribuire i binari perché la tua app è di origine chiusa e non vuoi dare il tuo codice sorgente.
  • Velocità, come i sistemi integrati e simili.
  • È necessario un livello di sicurezza del tipo di codice che solo un compilatore con un linguaggio rigorosamente tipizzato può darti. I compilatori espongono errori di battitura in ogni angolo del tuo codice sorgente, mentre nei programmi interpretati i refusi possono essere scoperti nel codice di produzione.
  • Sistemi grandi e complessi: non riesco a immaginare un sistema operativo o una tuta da ufficio come tutto tranne che binari compilati.
  • Vuoi evitare ogni piccolo overhead e hai bisogno di una buona comunicazione con i frammenti di assemblatore (difficile con qualsiasi tipo di runtime, specialmente con un interprete) (questo punto è determinato da un commento di @delnam)

3
Un interprete di lingue rende la lingua non meno tipizzata. Haskell è estremamente tipizzato e puoi usare GHCI per interpretarlo efficacemente. La tipizzazione forte / debole è aspetti di una lingua, non aspetti di un compilatore o interprete.
Jimmy Hoffa,

1
-1 Sui professionisti della compilazione: (1) Il codice di compilazione non protegge contro il reverse engineering, ma lo rende solo leggermente più difficile. (2) La compilazione (rimozione del sovraccarico dell'interprete, ottimizzazione automatizzata del codice dell'applicazione) è solo una fonte di prestazioni ed è superata da ottimizzazioni su larga scala fatte a mano da un esperto umano. (3) Il controllo del tipo, sebbene di solito associato alla compilazione, è indipendente da esso. Un controllo di tipo è un passaggio di analisi statica; può accadere senza emettere codice e prima di interpretare il codice. (4) Sembra abbastanza falso. "Non puoi immaginarlo"? Perché? Come è richiesto?

1
Altre lingue interpretate esistono ogni volta che c'è un interprete in un altro programma. Ogni volta che si utilizza il modello di interprete , esiste un linguaggio interpretato di una certa complessità.

3
gli "script" non sono necessariamente interpretati. Molti linguaggi di "scripting" sono compilati in bytecode per una macchina virtuale che viene quindi eseguita (vedi lua, perl, python, ruby). Non c'è alcuna differenza reale tra questo e java se non quando avviene la compilazione.

3
+1, penso che sia il tipo di risposta che l'OP stava davvero cercando, e sebbene i punti possano non essere veri al 100% come sottolineato, ci sono almeno il 95% veri per considerazioni pratiche.
Doc Brown,

1

Alla fine, il grande compromesso è tra produttività (quante righe di codice devi scrivere) e prestazioni (quanto velocemente il tuo programma verrà eseguito).

Poiché i linguaggi interpretati quando trasformati in informazioni sulla CPU hanno più informazioni, possono fare affidamento sulla riflessione e sulla digitazione dinamica che aumentano notevolmente la produttività . Un altro vantaggio delle lingue interpretate è che sono indipendenti dalla piattaforma così a lungo che esiste un interprete per la piattaforma.

Poiché la CPU non deve trasformare il codice della lingua in codice macchina ed eseguire il codice contemporaneamente, come nel caso interpretato, i linguaggi compilati producono programmi più veloci. Inoltre, un sistema costruito in un linguaggio compilato è più sicuro poiché può rilevare i problemi in fase di compilazione, il che significa sostanzialmente che vedi un errore mentre lo digiti (con IDE moderni) invece di vederlo solo quando esegui effettivamente il programma (ovviamente , questo non risolve errori logici).

Sapendo questo, le lingue interpretate sono adatte per:

  1. Sviluppo produttivo: sviluppo web veloce (PHP, Javascript) o per prototipazione.
  2. Cross-platform; ad esempio JavaScript è supportato in tutti i browser (inclusi i browser per dispositivi mobili).

E i linguaggi compilati sono adatti quando:

  1. Le prestazioni sono fondamentali (sistemi operativi) o le risorse sono scarse (microcontrollori).
  2. I sistemi da costruire sono complessi; quando si costruiscono linguaggi compilati di sistemi di grandi dimensioni (sistemi aziendali) sono essenziali per gestire molti possibili bug che possono apparire in linguaggi interpretati; anche i programmi complessi richiedono molte risorse e l'equilibrio tende anche alle lingue compilate.

-1 perché implica che tutte le lingue interpretate siano tipizzate dinamicamente e che tutte le lingue compilate siano tipizzate staticamente, il che è completamente falso.
Daniel Pryden,

@DanielPryden Quindi deve essere pura coincidenza, il fatto che quasi tutte le lingue interpretate siano tipizzate in modo dinamico e quelle compilate in modo statico? È una coincidenza che il modello di tipo dinamico sia adatto a linguaggi interpretati?
m3th0dman,

Per vari motivi, esiste una correlazione, ma non è un requisito. Questo è stato effettivamente chiesto su StackOverflow: Perché i lang interpretati sono per lo più a forma di anatra mentre la compilazione ha una digitazione forte?
Daniel Pryden,

1
Erlang è compilato e digitato in modo dinamico. Haskell è scritto staticamente e può essere compilato o interpretato
Zachary K

1
@ZacharyK Erlang ha un sistema di runtime; Haskell è compilato nella maggior parte dei casi (programmi scritti).
m3th0dman,

1

Oltre ai motivi citati dagli altri, esiste un caso d'uso particolarmente importante per la scelta di un'interpretazione ad hoc rispetto a qualsiasi forma di compilazione o approccio ibrido.

Nel caso in cui un linguaggio di programmazione sia utilizzato come protocollo di comunicazione e quando la latenza di risposta è importante, ha più senso evitare di perdere tempo nella compilazione e ogni possibile preelaborazione.

Questo vale per le lingue degli agenti, ad esempio, o per il modo in cui, ad esempio, Tcl / Tk viene normalmente utilizzato.

Un altro possibile motivo per attenersi all'interpretazione è quando un interprete di linguaggio viene utilizzato per l'avvio automatico o un linguaggio di livello superiore più elaborato e la sua semplicità è più importante delle prestazioni del processo bootstrap.

Per quasi tutti gli altri possibili casi d'uso, la compilazione (o un approccio ibrido) si adatta meglio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.