Greenspuns Zehnte Regel: Beinhaltet jedes große Projekt einen Lisp-Interpreten? [geschlossen]


12

Die zehnte Regel von Greenspun (eigentlich die einzige Regel) lautet:

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

Meiner Erinnerung nach gibt es einige Artikel zu diesem Thema, möglicherweise für Borlands Quattro-Projekt (Tabellenkalkulation) und möglicherweise für andere. Google ist nicht hilfreich. Vielleicht fallen Ihnen nicht die richtigen Suchbegriffe ein. Ich suche Papiere oder Artikel, die diese Behauptung stützen.


8
Haben Sie die Erklärung der Regelbedeutung im Wikipedia-Artikel gelesen ? Ich bezweifle, dass ernsthafte Anstrengungen unternommen werden würden, um die Behauptung zu bestätigen oder zu widerlegen. Sie sollte nicht wirklich ernst genommen werden .
Yannis

3
Das Lustige ist, dass ich, obwohl Greenspuns Regel nur ein Scherz war, tatsächlich an einer Simulationssoftware mit einem eingebetteten LISP-Interpreter gearbeitet habe. Die Konfiguration der Software erfolgte allesamt über S-Expressions, und man hätte sich vorstellen können, LISP-Code zu schreiben, um verschiedene Konfigurationsschritte auszuführen.
wkl

@YannisRizos - Wörtlich, keiner Ihrer Links behauptet, die Regel sei ein Witz. Morris 'Gesetz ist jedoch als solches gerahmt. Nun im übertragenen Sinne ...
casualcoder

2
@casualcoder "Es ist ironisch, dass dies nach meinem Tod wahrscheinlich die einzige Sache sein wird, an die sich irgendjemand von meinem Schreiben erinnert." und die Benennung der Regel deutet darauf hin, dass sie unbeschwert geschrieben wurde ...
yannis

Gab es nicht ein ähnliches Zitat in Bezug auf Erlang und gleichzeitige Programme?
Giorgio,

Antworten:


15

Die Aussage ist übertrieben. Aber in anderen Sprachen gibt es offensichtliche Anzeichen von Lisp-Neid. Schauen Sie sich C # an und wie es in der Natur immer funktionaler wird. Schauen Sie sich die verschiedenen Business Process Management-, Workflow- und EAI-Frameworks an, die im Weg stehen, damit das System programmiert werden kann, ohne das Programm zu ändern.

Es gibt ein Buch über domänenspezifische Sprachen von Martin Fowler, in dem erklärt wird, wie man Metaprogramme in objektorientierten Sprachen erstellt. Die Übertreibung hat also etwas Wahres.

Paul Graham nannte Lisp die mächtigste Sprache, wenn man sich die Liste der ersten mit Lisp gelieferten Sprachen ansieht. Es ist leicht zu erkennen, warum viele Sprachen im Vergleich blass sind.

Die Umgehung der zehnten Regel ist die Mehrsprachigkeit. Zu erkennen, dass eine Sprache / ein Framework nicht der goldene Hammer ist. Anstatt eine schlechte Ad-hoc-Implementierung von Lisp zu erstellen, können Sie einfach Lisp verwenden.


4
Macht und Alter sind unabhängig. Es ist wirklich ziemlich unerheblich, wie gut oder schlecht LISP zum Zeitpunkt seiner Erstellung war, es ist wichtig, wie es mit den heutigen Sprachen verglichen wird. Die Ersten sind völlig unwichtig.
DeadMG

2
@DeadMG, diese "Ersten" sind nichts im Vergleich zu den Dingen, die noch nicht von Lisp in die anderen Sprachen portiert wurden.
SK-logic

1
@DeadMG, du hast recht. Eines der Dinge, die die Leute an Ruby lieben, nachdem sie angefangen haben, darin zu graben, ist der Metaprogrammierungsaspekt. Lisp hat das eingebaut. C # -Entwickler lieben LINQ (aus gutem Grund) und die Auswirkungen, die deklarative Programmierung auf die Parallelität hat. Lisp hat das in Pik. Wenn Systeme komplexer werden, geht es mehr um Knoten, die auf Nachrichten reagieren, und weniger um Objekte. Lisp beginnt dort, die meisten anderen Sprachen müssen es entweder ad hoc (daher die Regel) oder über ein Framework (z. B. Biztalk, Tibco usw.) angehen.
Michael Brown

2
"Anstatt eine schlechte Ad-hoc-Implementierung von Lisp zu erstellen, können Sie einfach Lisp verwenden", aber Morris bedeutet, dass Sie immer noch eine schlechte Ad-hoc-Implementierung verwenden;)
jk.

1
Perfekte Ergänzung zu diesem Eintrag "Die gesamte Hacker-Kultur wird von Hackern oft als ha-ha-nur-ernst angesehen. Wenn sie zu leicht oder zu ernst genommen wird, wird eine Person als Außenseiter, Möchtegern-Jünger oder im Larvenstadium eingestuft . "
Michael Brown

10

Greenspuns "zehnte Regel" war ein Stück Snark. Wenn Sie weit genug gedehnt sind und "jedes Skript- oder Konfigurationssystem" abdecken, muss die Antwort auf diese Frage natürlich "Ja" lauten, da die Konfiguration etwas ist, was jedes nicht-triviale Programm in gewissem Maße erfordert, und Skripten ist nur geringfügig seltener, wenn Sie die Komplexitätsskala nach oben verschieben.

Schauen Sie sich andererseits GOAL an , eine von Naughty Dog für die Programmierung von Spielen erfundene Lisp-Variante. Es sieht überhaupt nicht nach "klassischem" Lisp aus. Es handelt sich um ein System mit einem hohen Imperativstil, objektorientierten Funktionen, keinem Interpreter, minimaler Unterstützung für die Garbage Collection (stattdessen werden Bereinigungsfunktionen auf Laufzeitebene benötigt) und umfassender Unterstützung für die Inline-Assemblierung.

Mit anderen Worten, als sie versuchten, Lisp für ein ausreichend komplexes Projekt zu verwenden, stellten sie fest, dass sie die Sprache in eine ad-hoc informell spezifizierte Implementierung der Hälfte von C ++ verwandeln mussten, um etwas Nützliches zu tun! ;) (Und sie mussten schließlich aufhören, nachdem der Typ, der GOAL entworfen hatte, gegangen war, weil niemand seinen Code verstehen konnte.)


Ich denke, meine Frage bezieht sich auf bestimmte Teile eines großen Systems. Irgendwann wird das System Teile haben, die aufgrund der Denkprozesse oder Techniken, die mit der Verwendung dieser Sprache verbunden sind, besser in einer anderen Sprache codiert sind, als inhärente Geschwindigkeit oder Überlegenheit. Die Geschichte von Herrn Lenaghan ist ein Beispiel.
Casualcoder

Tatsächlich haben sie die Verwendung von GOAL eingestellt, weil sie von einer Firma gekauft wurden, deren Codebasis C ++ war. Auch GOAL war ziemlich nervig. Gehen Sie nicht davon aus, dass Online-Tutorials und Vorlesungen mit dem kleinsten Nenner korrekt sind :)
p_l

9

Seltsamerweise ist eine Antwort auf diese Frage seltsamerweise bereits in der Programmers SE .

So zitieren Sie den relevanten Teil:

Greenspuns Argument war (teilweise), dass in vielen komplexen Programmen Interpreter eingebaut sind. Anstatt einen Interpreter in eine Sprache zu integrieren, schlug er vor, dass es sinnvoller sein könnte, eine Sprache wie Lisp zu verwenden, in der bereits ein Interpreter (oder Compiler) integriert ist.

Zu der Zeit arbeitete ich an einer ziemlich großen App, die benutzerdefinierte Berechnungen mit einem benutzerdefinierten Interpreter für eine benutzerdefinierte Sprache durchführte. Ich beschloss, seinen Kern in Lisp als großes Experiment neu zu schreiben.

Es dauerte ungefähr sechs Wochen. Der ursprüngliche Code war ~ 100.000 Zeilen Delphi (eine Pascal-Variante). In Lisp wurde das auf ~ 10.000 Zeilen reduziert. Noch überraschender war jedoch die Tatsache, dass die Lisp-Engine 3-6-mal schneller war. Und denken Sie daran, dass dies die Arbeit eines Lisp-Neulings war! Diese ganze Erfahrung hat mir die Augen geöffnet. Zum ersten Mal sah ich die Möglichkeit, Leistung und Ausdruckskraft in einer einzigen Sprache zu kombinieren.
- Michael Lenaghan

Um diesen Teil weiter zu verdeutlichen, antwortete Michael auf einen Kommentar mit:

Wow, das muss ein wirklich schrecklicher Delphi-Code gewesen sein, wenn es irgendwie gelungen ist, 3-6x langsamer als eine Lisp-Implementierung zu arbeiten! Benutzerausdrücke in Lisp-Ausdrücke umwandeln - ein trivial einfacher Vorgang - und dann die Lisp-Ausdrücke in nativen Code umwandeln (mit vollständiger Optimierung).
- Michael Lenaghan

Da diese Antwort aus der Antwort einer anderen Person besteht, handelt es sich um ein Community-Wiki.


2

Die Regel ist ein Witz, aber es steckt ein bisschen Wahrheit darin. Jedes komplexe System würde eine Reihe von interpretierten Teilen enthalten (siehe, wie beliebt das "Interpreter-Muster" bei jenen ist, die an all diese Muster glauben, die mumbo-jumbo sind). Jedes komplexe System muss Konfigurationsmittel bereitstellen, die häufig strukturiert und häufig interpretiert werden.

Es ist sehr wahrscheinlich, dass ein komplexes System in seinem Erstellungsprozess mehrere Codegenerierungsdurchläufe und verschiedene angepasste Präprozessoren aufweist (denken Sie an Dinge wie mocin Qt oder tablegenin LLVM).

Viele Systeme jonglieren mit (fast immer) schlecht gestalteten Tree-Walking- und Transformationswerkzeugen, die der Bibliotheksfunktionalität von Common Lisp sehr ähnlich sind, mit den komplexen baumartigen Datenstrukturen.

All diese Dinge sind mit Lisp kostenlos, und in den meisten Fällen wäre all das, was ad hoc, ungeplant und nicht gründlich genug durchdacht ist, äußerst minderwertig.


2

Jedes ausreichend komplexe System hat domänenspezifische Konzepte und Anforderungen, die mit den Abstraktionen der Sprache, in der Sie arbeiten, nur sehr schwer auszudrücken sind. Dies zwingt Programmierer versehentlich dazu, domänenspezifische Abstraktionen zu erstellen, um die Last der Überbrückung der semantischen Lücke zwischen den Programmiersprachen zu verringern und die spezifische Domäne. Sobald es genug von diesen Abstraktionen gibt, haben Sie im Grunde einen Interpreter einer domänenspezifischen Sprache. Dies ist ein unvermeidbarer Bestandteil der Softwareentwicklung.


1

Die Regel könnte wahrscheinlich genauer (und weniger amüsant) sein, da "jedes große softwarebasierte System erforderlich sein wird, um dynamisches Verhalten zu implementieren".

Dies kann auf zwei Arten geschehen:

  1. Eine große, komplexe Konfigurationsdatei mit Dutzenden von Parametern und Hunderten von Definitionen.

  2. Eine AD-HOC-Skriptsprache.

"sendmail" ist wahrscheinlich das kanonische Beispiel vom Typ "1". Ich kann mir keine guten Beispiele vom Typ "2" vorstellen, in denen keine "echte" Skriptsprache nach dem Vorbild von Warcraft / LUA oder sogar Netscape / Javascript eingebettet ist.

Das Problem ist, dass es für einige Parameter schnell und einfach ist, es mit einer Konfigurationsdatei zu tun, aber diese Lösung skaliert nicht wirklich. Es ist jedoch zu keinem Zeitpunkt wirtschaftlich, die Konfigurationsdatei zugunsten eines Skriptansatzes zu sichern, wenn der Konfigurationsdatei eine oder zwei Optionen hinzugefügt werden. Der Code, der die Konfigurationsdatei interpretiert, ist also ein wirklich schlecht geschriebener Interpreter.


0

Das mag stimmen, wie andere bereits sagten, viele Programme erfordern Konfigurierbarkeit und enthalten daher verschiedene lisp-ähnliche Interpreter.

Die Aussage impliziert jedoch auch mit einem Grinsen, dass alles, was Sie brauchen, um ein Programm zu erstellen, Lisp ist und dass alle anderen Sprachen ihm unterlegen sind.

Aber es ist falsch, Lisp mag expressiv sein, aber es ist auch zu abstrakt, es versucht, Details einer Plattform zu verbergen und so zu tun, als gäbe es in der Computerwelt nur Listen.

Die Realität der Hochleistungsprogrammierung ist, dass wir uns manchmal mit Bits und Bytes vermischen müssen und betriebssystemspezifische Dinge tun müssen, sodass es nicht möglich ist, alles nur mit Lisp zu tun, wie es die Anweisung impliziert.

Es ist eher umgekehrt, egal wie kompliziert, klug oder raffiniert eine Sprache ist, am Ende ist es nur eine andere Art, Assembler zu schreiben.


Scheint nur für die ältesten Lisp-Umgebungen der späten 50er relevant zu sein. Persönlich fand ich Common Lisps Funktionen für den Umgang mit Bits wahrscheinlich eine der besten (wobei der Hauptwettbewerb Erlang war). Arrays, Hashtables und Strukturen sind alle üblich.
p_l

Es ist einfach, Compiler für Lisp zu schreiben, da Sie es nicht analysieren müssen. Lisp-Funktionen könnten erstellt werden, und ein Makro-Compiler (der wie der Lisp-Evaluator zu Beginn nur eine bis eine halbe Seite Code enthält) verwandelt diese List-Ausdrücke in C, und Sie schreiben in Lisp in C, aber mit der ganzen Kraft von Makros und Lambda-Kalkül, wenn Sie wollen.
aoeu256

0

Ob es nun ernst genommen wurde oder nicht, es gilt für die größten C- und C ++ - Projekte, an denen ich gearbeitet habe.

Was nicht stimmt, ist, dass die benutzerdefinierten Skriptsprachen Common Lisp ähneln. Die positiven Beispiele ähneln dem Schema (weil die intelligenteren Designer Guile, SpiderMonkey und Lua integriert haben, anstatt ihre eigene Sprache zu erfinden.) Die Beispiele, die DailyWTF wert sind, waren eine Forth-ähnliche Sprache und eine MUMPS-ähnliche Sprache.

Ein anderes Beispiel (nicht sicher, ob es als Greenspunning, aber sicherlich als WTF gilt) war ein XSLT-Interpreter, der für allgemeine Skripterstellung verwendet wurde. Dies war mehr Lisp-ähnlich, da sie eine Rückkopplungsschleife hinzufügten, in der die Ausgabe ein zweites Mal XSLT-transformiert wurde - so dass Sie nun effektiv Makros haben.
Das Motiv hier war jedoch nicht, Zugriff auf Lispy-Funktionen zu erhalten, sondern die Code-QA-Prozeduren des Unternehmens zu umgehen (die zu jeder Fehlerbehebung 3 Wochen Latenz hinzufügten. XML wurde als "Daten" eingestuft und vom Prozess ausgenommen.)


-1

Leider nicht!

Während es am besten ist, nur einen echten lisp (y) -Interpreter einzubetten (Javascript oder lua alos leisten gute Arbeit), reduziert das Hinzufügen eines Homebrew 4gl zu einem Projekt die Gesamtgröße und erhöht gleichzeitig die Flexibilität.

Projekte, die "alles codieren", haben eine wesentlich größere Modulanzahl und werden unhandlich und unflexibel.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.