Decima regola di Greenspun, ogni grande progetto include un interprete Lisp? [chiuso]


12

La decima regola di Greenspun (in realtà l'unica regola) afferma che:

Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.

La mia memoria è che ci sono alcuni articoli sull'argomento, forse per il progetto Quattro (foglio di calcolo) di Borland e forse altri. Google non aiuta, forse non vengono in mente i termini di ricerca giusti. Sto cercando documenti o articoli a supporto di questa affermazione, se presente.


8
Hai letto la spiegazione del significato della regola sull'articolo di Wikipedia? Dubito che ci sarebbero sforzi seri per confermare o confutare il reclamo, in realtà non doveva essere preso sul serio .
yannis,

3
La cosa divertente è che mentre la regola di Greenspun era solo uno scherzo, in realtà ho lavorato su un software di simulazione con un interprete LISP incorporato. La configurazione del software è stata fatta tramite S-Expressions e si potrebbe presumibilmente aver scritto il codice LISP per fare varie cose nella configurazione.
wkl,

@YannisRizos - Letteralmente, nessuno dei tuoi link afferma che la Regola è uno scherzo. Ma la legge di Morris è inquadrata come tale. Ora, in senso figurato ....
casualcoder,

2
@casualcoder "È ironico che questa, dopo la mia morte, sarà probabilmente l'unica cosa che qualcuno ricorda dalla mia scrittura." e la denominazione della regola suggerisce che è stata scritta in modo spensierato ...
yannis,

Non c'era una citazione simile per quanto riguarda Erlang e i programmi concorrenti?
Giorgio

Risposte:


15

L'istruzione è iperbole. Ma ci sono segni evidenti dell'invidia di Lisp in altre lingue. Guarda C # e come sta diventando più funzionale in natura. Guarda i vari quadri di gestione dei processi aziendali, flusso di lavoro e EAI che fanno del loro meglio per rendere possibile la programmazione del sistema senza modificare il programma.

C'è un libro sui linguaggi specifici del dominio di Martin Fowler che parla di come eseguire la meta-programmazione in linguaggi orientati agli oggetti. Quindi c'è un po 'di verità nell'iperbole.

Paul Graham chiamava Lisp la lingua più potente guardando l' elenco dei primi che arrivavano con Lisp , è facile capire perché molte lingue impallidiscono in confronto.

Il modo per aggirare la decima regola è la programmazione poliglotta. Rendersi conto che una lingua / quadro non è il martello d'oro. Quindi, invece di creare un'implementazione scadente e ad hoc di Lisp, puoi semplicemente usare Lisp.


4
Potenza ed età sono indipendenti. È davvero irrilevante quanto LISP sia stato buono o cattivo al momento della sua creazione, è importante come si confronta con le lingue di oggi. I primi sono assolutamente irrilevanti.
DeadMG

2
@DeadMG, questi "primi" non sono nulla in confronto alle cose che non sono ancora state portate da Lisp verso le altre lingue.
SK-logic,

1
@DeadMG, hai ragione. Una delle cose che la gente ama di Ruby dopo aver iniziato a scavare è l'aspetto Metaprogramming di esso. Lisp ha questo integrato. Gli sviluppatori di C # adorano LINQ (per una buona ragione) e le implicazioni che la programmazione dichiarativa ha sulla concorrenza. Lisp lo ha a palate. Man mano che i sistemi diventano più complessi, diventano più circa i nodi che reagiscono ai messaggi e meno sugli oggetti. Lisp inizia da lì, la maggior parte delle altre lingue deve affrontarla ad hoc (da cui la regola) o attraverso un framework (ad esempio Biztalk, Tibco, ecc.).
Michael Brown,

2
"invece di creare un'implementazione scadente e ad hoc di Lisp, puoi semplicemente usare Lisp" ma il corollario di Morris significa che stai ancora utilizzando un'implementazione scarsa e ad hoc;)
jk.

1
Perfetto sidenote per quella voce "l'intera cultura degli hacker è spesso percepita come ha-ha-solo-seria dagli stessi hacker; prenderla in modo troppo leggero o troppo serio segna una persona come un estraneo, un aspirante o in fase larvale . "
Michael Brown,

10

La "decima regola" di Greenspun era un po 'fuori controllo. Se esteso abbastanza, se lo fai coprire "qualsiasi sistema di scripting o di configurazione", ovviamente la risposta a questa domanda dovrà essere "sì", poiché la configurazione è qualcosa che un programma non banale richiede in una certa misura e scripting è solo leggermente meno comune quando si sale la scala della complessità.

D'altra parte, dai un'occhiata a GOAL , una variante Lisp inventata da Naughty Dog per la programmazione del gioco. Non assomiglia per niente al Lisp "classico". È un sistema in stile altamente imperativo, con funzionalità orientata agli oggetti, nessun interprete, supporto minimo per la garbage collection (basandosi invece su strutture di pulizia a livello di runtime) e ampio supporto per l'assemblaggio in linea.

In altre parole, quando hanno cercato di usare Lisp per un progetto sufficientemente complesso, hanno scoperto che per fare qualcosa di utile dovevano trasformare la lingua in un'implementazione ad hoc, specificata in modo informale di metà del C ++! ;) (E alla fine hanno dovuto smettere di usarlo dopo che il ragazzo che ha progettato GOAL se ne è andato, perché nessuno poteva capire il suo codice.)


Immagino che la mia domanda riguardi parti specifiche di un sistema di grandi dimensioni. Alla fine, il sistema avrà parti che sono meglio codificate in un'altra lingua a causa dei processi di pensiero o delle tecniche coinvolte nell'uso di quella lingua, piuttosto che della velocità o della superiorità intrinseca. La storia del signor Lenaghan è un esempio.
casualcoder

In realtà, hanno smesso di usare GOAL perché sono stati acquistati dalla società il cui codice base era in C ++. Inoltre, GOAL è stato abbastanza piacevole. Non dare per scontato che i tutorial in linea con il denominatore più basso e le lezioni universitarie siano corretti :)
p_l

9

Curiosamente, una risposta a questa domanda è già in Programmers SE .

Per citare la parte pertinente:

Il punto di Greenspun era (in parte) che molti programmi complessi hanno interpreti incorporati. Invece di costruire un interprete in una lingua, ha suggerito che potrebbe avere più senso usare una lingua come Lisp che ha già un interprete (o un compilatore) incorporato.

All'epoca lavoravo su un'app piuttosto grande che eseguiva calcoli definiti dall'utente usando un interprete personalizzato per un linguaggio personalizzato. Ho deciso di provare a riscrivere il suo core in Lisp come esperimento su larga scala.

Ci sono volute circa sei settimane. Il codice originale era ~ 100.000 righe di Delphi (una variante Pascal). In Lisp che è stato ridotto a ~ 10.000 linee. Ancora più sorprendente, tuttavia, è stato il fatto che il motore Lisp era 3-6 volte più veloce. E tieni presente che questo era il lavoro di un neofita di Lisp! Tutta questa esperienza mi ha aperto gli occhi; per la prima volta ho visto la possibilità di combinare prestazioni ed espressività in una sola lingua.
- Michael Lenaghan

Per chiarire ulteriormente quella parte, Michael ha risposto a un commento con:

Wow, deve essere stato un codice Delphi davvero orribile se in qualche modo è riuscito a eseguire 3-6 volte più lentamente di un'implementazione Lisp! "Giusto, lo considererò come un mio fallimento per non averlo spiegato meglio. L'implementazione di Lisp è stata in grado di trasformare espressioni utente in espressioni Lisp - un processo banalmente facile - e quindi compilare le espressioni Lisp in codice nativo (con ottimizzazione completa). Questo è il significato della Decima Regola di Greenspun.
-– Michael Lenaghan

Dato che questa risposta è composta dalla risposta di qualcun altro altrove, è wiki della comunità.


2

La regola è uno scherzo, ma contiene un po 'di verità. Qualsiasi sistema complesso conterrebbe un numero di parti interpretate (vedi, come il "modello dell'interprete" è popolare tra coloro che credono in tutto quel modello mumbo-jumbo). Qualsiasi sistema complesso deve fornire alcuni mezzi di configurazione, spesso strutturati, spesso interpretati.

È probabile che qualsiasi sistema complesso abbia diversi passaggi di generazione del codice e vari preprocessori personalizzati nel suo processo di compilazione (pensate a cose come mocin Qt o tablegenin LLVM).

Molti sistemi si destreggiano tra le complesse strutture di dati simili ad alberi utilizzando set di alberi quasi sempre mal progettati e trasformando strumenti che assomigliano molto alla funzionalità della libreria di Common Lisp.

Tutte queste cose sono gratuite con Lisp, e nella maggior parte dei casi tutte quelle ad hoc, non pianificate, non pensate con implementazioni abbastanza approfondite sarebbero assolutamente inferiori.


2

Qualsiasi sistema sufficientemente complesso avrà concetti e requisiti specifici del dominio che sono estremamente difficili da esprimere con le astrazioni della lingua in cui stai lavorando. Ciò costringe inavvertitamente i programmatori a creare astrazioni specifiche del dominio per alleviare l'onere di colmare il divario semantico tra il linguaggio di programmazione e il dominio specifico. Una volta che ci sono abbastanza di queste astrazioni, fondamentalmente hai un interprete di una lingua specifica del dominio. Questa è una parte inevitabile dello sviluppo del software.


1

La regola potrebbe essere probabilmente più accurata (e meno divertente) in quanto "per implementare comportamenti dinamici sarà richiesto ogni grande sistema basato su software".

Questo può essere fatto in due modi-

  1. Un grande file di configurazione complesso con dozzine di parametri e centinaia di definizioni.

  2. Un linguaggio di script AD-HOC.

"sendmail" è probabilmente l'esempio canonico di tipo "1". Non riesco a pensare a nessun buon esempio di tipo "2" che non implichi l'incorporamento di un "vero" linguaggio di scripting in Warcraft / LUA o Netscape / Javascript.

Il problema è che per alcuni parametri è semplice e veloce farlo con un file di configurazione, ma questa soluzione non si adatta. Tuttavia, in nessun momento sarà economico scaricare il file di configurazione a favore di un approccio di script quando si aggiungono una o due opzioni al file di configurazione. Quindi il codice che interpreta il file di configurazione finisce per essere un interprete scritto davvero male.


0

Questo può essere vero, come altri hanno affermato, molti programmi richiedono configurabilità e quindi contengono vari interpreti di tipo lisp.

Tuttavia, l'affermazione implica anche con un sorrisetto che tutto ciò che serve per creare un programma è Lisp e che tutte le altre lingue sono inferiori ad esso.

Ma è sbagliato, Lisp può essere espressivo, ma è anche troppo astratto, cerca di nascondere i dettagli di una piattaforma e finge che non esistano elenchi nel mondo dei computer.

La realtà della programmazione ad alte prestazioni è che a volte abbiamo bisogno di mescolarci con bit e byte e fare cose specifiche del sistema operativo, quindi non è possibile fare tutto con solo Lisp come implica l'istruzione.

È piuttosto il contrario, non importa quanto complicato, intelligente o sofisticato di un linguaggio che inventi, tutto ciò che finisce per essere è solo un altro modo di scrivere assembly.


Sembra rilevante solo per gli ambienti lisp più antichi della fine degli anni '50. Personalmente, ho trovato le funzioni di Common Lisp per gestire i bit probabilmente una delle migliori (con Erlang la concorrenza principale). Matrici, hashtabili, strutture sono tutti comuni.
p_l

È facile scrivere compilatori per Lisp in quanto non è necessario analizzarlo. Potrebbero essere create funzioni di Lisp e un compilatore di macro (che è come il valutatore di Lisp solo da una a mezza pagina di codice all'inizio) che trasforma quelle espressioni di Elenco in C, e tu scrivi in ​​C in Lisp ma con tutta la potenza di macro e calcolo lambda se vuoi.
aoeu256,

0

Indipendentemente dal fatto che dovesse essere preso sul serio o meno, è vero per i più grandi progetti C e C ++ a cui ho lavorato.

Ciò che non è vero è che i linguaggi di script personalizzati assomigliano a Common Lisp. Gli esempi positivi assomigliano a Scheme (perché i progettisti più intelligenti hanno integrato Guile, SpiderMonkey e Lua invece di inventare la propria lingua). Gli esempi più degni di DailyWTF sono stati un linguaggio simile a Forth e un linguaggio simile a MUMPS.

Un altro esempio (non sicuro se conta come Greenspunning, ma sicuramente un WTF) è stato un interprete XSLT utilizzato per gli script per scopi generici. Questo è stato più simile a Lisp in quanto hanno aggiunto un loop di feedback in cui l'output sarebbe stato trasformato XSLT una seconda volta, quindi ora hai effettivamente macro.
Il motivo qui non era quello di ottenere l'accesso a funzionalità lispy ma di eludere le procedure di QA del codice dell'azienda (che aggiungevano 3 settimane di latenza a ogni correzione di bug. XML era considerato "dati" ed esente dal processo.)


-1

Sfortunatamente no!

Mentre è meglio incorporare un vero interprete lisp (y) (javascript o lua alos fa un buon lavoro), l'aggiunta di un homebrew 4gl a un progetto riduce le dimensioni complessive aumentando la flessibilità.

I progetti che "codificano tutto" hanno un numero di moduli notevolmente maggiore e diventano ingombranti e poco flessibili.

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.