Warum sind Standardbibliotheken keine Programmiersprachenprimitive? [geschlossen]


30

Ich dachte, warum gibt es (in allen Programmiersprachen, die ich gelernt habe, wie C ++, Java, Python) Standardbibliotheken wie stdlib, anstatt ähnliche "Funktionen" zu haben, die ein Grundelement der Sprache selbst sind.


4
Was meinen Sie mit "warum konnte der Compiler einen Funktionsaufruf nicht einfach in eine Reihe von Anweisungen übersetzen"? Das ist ungefähr das, was der Compiler macht, Standardbibliothek oder nicht (Ok, Python nur teilweise und Java zu JVM-Bytecode; ähnliches Konzept). Standardbibliotheken haben wirklich nichts mit der Kompilierung von Code -> Anweisungen zu tun.
Delioth

25
@Delioth Ich denke, Simone fragt sich, warum nicht alles in der Standardbibliothek der Sprache $ LANG stattdessen ein primitives Konstrukt / eine primitive Funktion dieser Sprache ist. Ich würde sagen, es ist eine vernünftige Frage für alle, die Programmiersprachen sehr neu sind :)
Andres F.

33
Die Standardbibliothek füllt im Allgemeinen die Lücke zwischen einer funktionierenden und einer nützlichen Programmiersprache .
Telastyn

6
Ein wesentlicher Teil der Python-Standardbibliothek ist in C geschrieben und bereits kompiliert.
ElmoVanKielmo

1
Im Gegensatz dazu ist in den meisten Implementierungen von BASIC alles Teil der Sprache, und es gibt überhaupt keine Bibliotheken und keine Unterstützung für diese (außer in mehreren Implementierungen für die Fähigkeit, Routinen in Maschinensprache aufzurufen).
Euro Micelli

Antworten:


32

Lassen Sie mich die gute Antwort von @ Vincent (+1) etwas näher erläutern :

Warum konnte der Compiler einen Funktionsaufruf nicht einfach in eine Reihe von Anweisungen übersetzen?

Es kann und tut dies über mindestens zwei Mechanismen:

  • Inlining eines Funktionsaufrufs - Während der Übersetzung kann der Compiler einen Quellcodeaufruf mit seiner Implementierung direkt inline ersetzen, anstatt die Funktion tatsächlich aufzurufen. Trotzdem muss für die Funktion irgendwo eine Implementierung definiert sein, die sich in der Standardbibliothek befinden kann.

  • intrinsische Funktion - intrinsische Funktionen sind Funktionen, über die der Compiler informiert wurde, ohne dass die Funktion in einer Bibliothek gefunden werden muss. Diese sind normalerweise für Hardwarefunktionen reserviert, auf die auf andere Weise praktisch nicht zugegriffen werden kann, da sie so einfach sind, dass selbst der Aufwand für den Aufruf der Assembler-Bibliotheksfunktion als hoch angesehen wird. (Der Compiler kann im Allgemeinen nur automatisch Quellcode in seiner Sprache einbinden, nicht jedoch Assembly-Funktionen. Hier kommt der eigentliche Mechanismus ins Spiel.)

Trotzdem ist es manchmal die beste Option für den Compiler, einen Funktionsaufruf in der Quellsprache in einen Funktionsaufruf im Maschinencode zu übersetzen. Rekursion, virtuelle Methoden und reine Größe sind einige Gründe, warum Inlining nicht immer möglich / praktisch ist. (Ein weiterer Grund ist die Absicht des Builds, z. B. separate Kompilierung (Objektmodule), separate Ladeeinheiten (z. B. DLLs)).

Es hat keinen wirklichen Vorteil, die meisten Standardbibliotheksfunktionen in den Griff zu bekommen (das würde viel mehr Wissen in den Compiler einschleusen, ohne einen wirklichen Vorteil zu erzielen), daher ist ein erneuter Aufruf des Maschinencodes häufig am besten geeignet.

C ist eine bemerkenswerte Sprache, die wohl andere explizite Sprachanweisungen zugunsten von Standardbibliotheksfunktionen weggelassen hat. Obwohl es bereits Bibliotheken gab, verlagerte sich diese Sprache dahingehend, mehr Arbeit von Standard-Bibliotheksfunktionen und weniger als explizite Aussagen in der Grammatik der Sprache zu leisten. Beispielsweise wurde IO in anderen Sprachen häufig eine eigene Syntax in Form verschiedener Anweisungen gegeben, während die C-Grammatik keine IO-Anweisungen definiert, sondern sich einfach auf ihre Standardbibliothek bezieht, um dies zu ermöglichen, die alle über Funktionsaufrufe zugänglich sind Der Compiler weiß bereits, wie es geht.


3
Gute Antwort. Man sollte ein paar Worte hinzufügen, warum diese Entscheidung in C getroffen wurde: Wenn ich mich recht erinnere, lag der Hauptgrund darin, dass es einfacher war, C-Compiler für viele verschiedene Hardwarearchitekturen zu erstellen.
Doc Brown

10
@DocBrown Bis 1975 gab es genügend Beispiele im Bereich der Programmiersprachenentwicklung (ALGOL-68, irgendjemand?), Die zeigten, dass Versuche, alles direkt in die Sprache einzubinden, zu beträchtlichen Verlangsamungen bei der Festlegung der Sprachspezifikationen und führten bei der Erstellung von Sprachimplementierungen.
Joker_vD

5
Ein ähnliches Beispiel gab es in Python print: In 2.x war es eine Anweisung mit einer eigenen speziellen Grammatik, aber in 3.x wurde es nur ein weiterer Funktionsaufruf. Siehe PEP 3105 für die offizielle Erklärung.
29.

1
@ DocBrown, Portabilität war mit ziemlicher Sicherheit kein Grund. Als Unix und C erstellt wurden, wurden sie für genau eine Maschine entwickelt und gebaut, einen Ersatz-PDP-7. Ken Thompson fragte sich, welche Konzepte aus dem fehlgeschlagenen Multics-Projekt geborgen werden könnten. C wurde auch aus einem Grund entwickelt: um eine Hochsprache zu haben, in der Unix (neu) implementiert werden kann. Sie sind im Grunde genommen ein Experiment im Bereich Software-Design, kein ernstzunehmender Versuch, ein kommerzielles Betriebssystem und eine Sprache für mehrere Plattformen zu entwickeln. Siehe beispielsweise bell-labs.com/usr/dmr/www/chist.html .
Euro Micelli

@EuroMicelli: Ich sehe da keinen Widerspruch. Und Ihre Referenz enthält viele Details darüber, wann Portabilität wichtig wurde, und zwar in den Anfangsjahren der C- und Unix-Entwicklung. Ich kann hier nur raten, aber wenn die C-Erfinder die Sprache nicht absichtlich klein gehalten hätten, wäre es ziemlich unwahrscheinlich gewesen, dass sie sie so schnell und erfolgreich auf viele verschiedene Architekturen portiert hätten.
Doc Brown

70

Dies ist einfach, um die Sprache selbst so einfach wie möglich zu halten. Sie müssen zwischen einer Funktion der Sprache, z. B. einer Art Schleife oder Möglichkeiten zum Übergeben von Parametern an Funktionen usw., und allgemeinen Funktionen, die die meisten Anwendungen benötigen, unterscheiden.

Bibliotheken sind Funktionen, die für viele Programmierer nützlich sein können, sodass sie als wiederverwendbarer Code erstellt werden, der gemeinsam genutzt werden kann. Die Standardbibliotheken sind so konzipiert, dass sie häufig von Programmierern benötigte Funktionen darstellen. Auf diese Weise ist die Programmiersprache für ein breiteres Spektrum von Programmierern sofort nützlich. Die Bibliotheken können aktualisiert und erweitert werden, ohne die Kernfunktionen der Sprache selbst zu ändern.


3
Nicht immer. PHPBeispielsweise macht es kaum einen Unterschied zwischen seinen umfangreichen Sprachfunktionen und der Sprache selbst.
Vahid Amiri

15
Ich würde PHP nicht als Beispiel für eine einfache Sprache nehmen
DrBreakalot

3
@ DrBreakalot PHP ist eine extrem einfache Sprache. Das heißt nicht, dass es ein einheitliches Design hat, aber das ist ein anderes Problem.
Leichtigkeit Rennen mit Monica

19
@LightnessRacesinOrbit Ich würde PHP überhaupt nicht als "einfach" bezeichnen: Es hat ein klassenbasiertes Objektsystem, eine separate Menge von "primitiven Werten", eigenständige Funktionen, erstklassige Abschlüsse, die auf dem Objektsystem basieren, einen Namespace-Mechanismus und vieles mehr Begriffe als „static“, Aussagen sowie Ausdrücke, include, requireund require_once, wenn / for / while (strukturierte Programmierung), Ausnahmen, ein separates System von ‚Fehlerwerte‘ schwache Typisierung Regeln kompliziert, Betreiber Vorrangregeln kompliziert, und so weiter . Vergleichen Sie dies mit der Einfachheit von beispielsweise Smalltalk, Schema, Prolog, Forth usw.;)
Warbo

3
Der Hauptgrund, der in dieser Antwort angedeutet, aber nicht explizit genannt wird, ist, dass die Implementierung auf anderen Plattformen viel einfacher ist, wenn die Sprache so einfach wie möglich gehalten wird. Da die Standardbibliotheken normalerweise in der Sprache selbst geschrieben sind , können sie einfach portiert werden.
BlueRaja - Danny Pflughoeft

34

Zusätzlich zu den anderen Antworten ist das Einfügen von Standardfunktionen in eine Bibliothek eine Trennung von Bedenken :

  • Es ist die Aufgabe des Compilers, die Sprache zu analysieren und Code dafür zu generieren. Es ist nicht die Aufgabe des Compilers, irgendetwas zu enthalten, das bereits in dieser Sprache geschrieben und als Bibliothek bereitgestellt werden kann.

  • Dies ist die Aufgabe der Standardbibliothek (die immer implizit verfügbar ist), um die Kernfunktionalität bereitzustellen , die von praktisch allen Programmen benötigt wird. Es ist nicht die Aufgabe der Standardbibliothek, alle Funktionen zu enthalten, die nützlich sein könnten.

  • Optionale Standardbibliotheken haben die Aufgabe, Zusatzfunktionen bereitzustellen, auf die viele Programme verzichten können, die jedoch immer noch recht einfach und für viele Anwendungen unerlässlich sind, um den Versand in Standardumgebungen zu gewährleisten. Es ist nicht die Aufgabe dieser optionalen Bibliotheken, den gesamten wiederverwendbaren Code zu enthalten, der jemals geschrieben wurde.

  • Es ist Aufgabe der Benutzerbibliotheken, Sammlungen nützlicher wiederverwendbarer Funktionen bereitzustellen. Es ist nicht die Aufgabe von Benutzerbibliotheken, den gesamten Code zu enthalten, der jemals geschrieben wurde.

  • Es ist die Aufgabe des Quellcodes einer Anwendung, die verbleibenden Codebits bereitzustellen, die wirklich nur für diese eine Anwendung relevant sind.

Wenn Sie eine einheitliche Software suchen, bekommen Sie etwas wahnsinnig Komplexes. Sie müssen modularisieren, um die Komplexität auf ein überschaubares Maß zu reduzieren. Und Sie müssen modularisieren , damit Teil Implementierungen:

  • Die Threading-Bibliothek ist auf dem Single-Core-Embedded-Controller wertlos. Es pthreadist genau das Richtige, zuzulassen, dass die Sprachimplementierung für diesen eingebetteten Controller die Bibliothek nicht einbezieht.

  • Die Mathematikbibliothek ist auf dem Mikrocontroller ohne FPU wertlos. Auch hier sin()macht es den Implementierern Ihrer Sprache das Leben für diesen Mikrocontroller sehr viel einfacher , nicht gezwungen zu sein, Funktionen wie bereitzustellen .

  • Selbst die Standard-Kernbibliothek ist wertlos, wenn Sie einen Kernel programmieren. Sie können nicht write()ohne einen Systemaufruf in den Kernel implementieren, und Sie können nicht printf()ohne implementieren write(). Als Kernel-Programmierer ist es Ihre Aufgabe, den write()Syscall bereitzustellen . Sie können nicht einfach erwarten, dass er da ist.

Eine Sprache, die solche Auslassungen in den Standardbibliotheken nicht zulässt, ist für viele Aufgaben einfach nicht geeignet . Wenn Sie möchten, dass Ihre Sprache in ungewöhnlichen Umgebungen flexibel verwendet werden kann, muss sie in den enthaltenen Standardbibliotheken flexibel sein. Je mehr sich Ihre Sprache auf Standardbibliotheken stützt, desto mehr Annahmen werden in Bezug auf die Ausführungsumgebung getroffen und daher auf Umgebungen beschränkt, die diese Voraussetzungen erfüllen.

Natürlich können Hochsprachen wie Python und Java eine Menge Annahmen über ihre Umgebung machen. Und sie neigen dazu, viele, viele Dinge in ihre Standardbibliotheken aufzunehmen. Untergeordnete Sprachen wie C stellen in ihren Standardbibliotheken viel weniger zur Verfügung und halten die Kernstandardbibliothek viel kleiner. Aus diesem Grund finden Sie einen funktionierenden C-Compiler für praktisch jede Architektur, der jedoch möglicherweise keine Python-Skripte ausführen kann.


16

Ein wichtiger Grund für die Trennung von Compilern und Standardbibliotheken besteht darin, dass sie zwei unterschiedlichen Zwecken dienen (auch wenn beide durch dieselbe Sprachspezifikation definiert sind): Der Compiler übersetzt Code höherer Ebene in Maschinenanweisungen, und die Standardbibliothek bietet vorab getestete Funktionen Implementierungen von häufig benötigten Funktionen. Compiler-Autoren legen genau wie andere Software-Entwickler Wert auf Modularität. Einige der frühen C-Compiler haben den Compiler sogar in separate Programme zur Vorverarbeitung, Kompilierung und Verknüpfung aufgeteilt.

Diese Modularität bietet Ihnen eine Reihe von Vorteilen:

  • Es minimiert den Arbeitsaufwand bei der Unterstützung einer neuen Hardwareplattform, da der Großteil des standardmäßigen Bibliothekscodes hardwareunabhängig ist und wiederverwendet werden kann.
  • Eine Standard-Bibliotheksimplementierung kann auf verschiedene Arten optimiert werden (hinsichtlich Geschwindigkeit, Speicherplatz, Ressourcennutzung usw.). Viele frühe Computersysteme verfügten nur über einen Compiler, und dank einer separaten Standardbibliothek konnten Entwickler Implementierungen entsprechend ihren Anforderungen austauschen.
  • Die Standard-Bibliotheksfunktionalität muss nicht einmal vorhanden sein. Wenn Sie beispielsweise Bare-Metal-C-Code schreiben, verfügen Sie über einen Compiler mit vollem Funktionsumfang, aber die meisten Funktionen der Standardbibliothek sind nicht vorhanden, und einige Dinge wie Datei-E / A sind nicht einmal möglich. Wenn der Compiler diese Funktionalität implementieren musste, konnte es auf einigen Plattformen, auf denen Sie sie am meisten benötigen, keinen standardkonformen C-Compiler geben.
  • Auf frühen Systemen wurden Compiler häufig von dem Unternehmen entwickelt, das die Hardware entworfen hat. Standardbibliotheken wurden häufig vom Betriebssystemhersteller bereitgestellt, da sie häufig Zugriff auf Funktionen (wie Systemaufrufe) erforderten, die für diese Softwareplattform spezifisch sind. Für einen Compiler-Schreiber war es unpraktisch, die verschiedenen Kombinationen von Hardware und Software zu unterstützen (früher gab es eine viel größere Vielfalt sowohl in der Hardware-Architektur als auch in der Software-Plattform).
  • In Hochsprachen kann eine Standardbibliothek als dynamisch geladene Bibliothek implementiert werden. Eine Standard-Bibliotheksimplementierung kann dann von mehreren Compilern und / oder Programmiersprachen verwendet werden.

Historisch gesehen (zumindest aus Sicht von C) hatten die ursprünglichen Vorstandardisierungsversionen der Sprache überhaupt keine Standardbibliothek. Betriebssystemhersteller und Drittanbieter stellten häufig Bibliotheken mit häufig verwendeten Funktionen zur Verfügung. Unterschiedliche Implementierungen umfassten jedoch unterschiedliche Aspekte und waren weitgehend inkompatibel. Als C standardisiert wurde, definierten sie eine "Standardbibliothek", um diese unterschiedlichen Implementierungen zu harmonisieren und die Portabilität zu verbessern. Die C-Standardbibliothek wurde unabhängig von der Sprache entwickelt, wie die Boost-Bibliotheken für C ++, wurden aber später in die Sprachspezifikation integriert.


6

Zusätzliche Eckantwort: Intellectual Property Management

Ein bemerkenswertes Beispiel ist die Implementierung von Math.Pow (double, double) in .NET Framework, das von Microsoft von Intel gekauft wurde und auch dann nicht veröffentlicht wird, wenn das Framework Open Source ist. (Um genau zu sein, im obigen Fall handelt es sich nicht um eine Bibliothek, sondern um einen internen Aufruf.) Eine von der Sprache selbst getrennte Bibliothek (theoretisch auch eine Teilmenge von Standardbibliotheken) kann den Unterstützern der Sprache mehr Flexibilität beim Zeichnen der zwischen dem, was transparent zu halten ist, und dem, was geheim zu halten ist (aufgrund von Verträgen mit Dritten oder aus anderen Gründen des geistigen Eigentums).


Das ist verwirrend. Auf der Seite, zu der Sie einen Link Math.Powerstellen, wird weder ein Kauf noch etwas über Intel erwähnt. Es handelt sich um Personen, die den Quellcode für die Implementierung der Funktion lesen.
Leichtigkeit Rennen mit Monica

@LightnessRacesinOrbit - hm, ich kann es immer noch dort sehen (bei der Suche nach "Intel"). Sie finden auch den Verweis auf den aktuellen Quellcode (in den neuesten Kommentaren) sowie eine alternative Implementierung (in der zweiten Antwort), die öffentlich verfügbar ist, deren Komplexität und kommentierte Ineffizienz jedoch einen Hinweis darauf gibt, warum die ursprüngliche Implementierung immer noch nicht veröffentlicht wird. Für eine wirklich effiziente Implementierung ist möglicherweise eine gründliche Kenntnis vieler Details auf CPU-Ebene erforderlich, die nicht unbedingt öffentlich verfügbar sind.
Miroxlav

5

Bugs und Debugging.

Bugs: Alle Software hat Bugs, Ihre Standardbibliothek hat Bugs und Ihr Compiler hat Bugs. Als Benutzer der Sprache ist es viel einfacher, solche Fehler zu finden und zu umgehen, wenn sie in der Standardbibliothek und nicht im Compiler vorhanden sind.

Debugging: Es ist für mich viel einfacher, einen Stack-Trace einer Standardbibliothek zu sehen und mir ein Gefühl dafür zu geben, was möglicherweise schief geht. Weil diese Stapelverfolgung Code hat, verstehe ich. Natürlich können Sie tiefer graben und Ihre inneren Funktionen nachvollziehen, aber es ist viel einfacher, wenn Sie eine Sprache verwenden, die Sie von Tag zu Tag verwenden.


5

Das ist eine ausgezeichnete Frage!

Der letzte Stand der Technik

Der C ++ - Standard gibt beispielsweise niemals an, was im Compiler oder in der Standardbibliothek implementiert werden soll: Er bezieht sich nur auf die Implementierung . Beispielsweise werden reservierte Symbole sowohl vom Compiler als auch von der Standardbibliothek austauschbar definiert.

Alle mir bekannten C ++ - Implementierungen haben jedoch die geringstmögliche Anzahl von vom Compiler bereitgestellten Inhalten und so viel wie möglich von der Standardbibliothek.

Obwohl es technisch machbar ist, die Standardbibliothek im Compiler als intrinsische Funktionalität zu definieren, scheint sie in der Praxis selten verwendet zu werden.

Warum?

Betrachten wir die Idee, einige Funktionen aus der Standardbibliothek in den Compiler zu verschieben.

Vorteile:

  • Bessere Diagnose: Intrinsics können speziell behandelt werden.
  • Bessere Leistung: Intrinsics können speziell behandelt werden.

Nachteile:

  • Erhöhte Compiler-Masse: Jeder Sonderfall erhöht die Komplexität des Compilers. Komplexität erhöht die Wartungskosten und die Wahrscheinlichkeit von Fehlern.
  • Langsamere Iteration: Wenn Sie die Implementierung der Funktionalität ändern, müssen Sie den Compiler selbst ändern. Dadurch wird es schwieriger, nur eine kleine Bibliothek (außerhalb von std) zum Experimentieren zu erstellen .
  • Höhere Eintrittsschwelle: Je teurer / schwieriger es ist, etwas zu ändern, desto weniger Menschen werden wahrscheinlich hineinspringen.

Dies bedeutet, dass das Verschieben von Daten in den Compiler jetzt und in Zukunft teuer ist und daher einen soliden Fall erfordert. Für einige Funktionen ist es erforderlich (sie können nicht als regulärer Code geschrieben werden), aber selbst dann lohnt es sich, minimale und generische Teile zu extrahieren , um sie in den Compiler zu verschieben und in der Standardbibliothek darauf zu erstellen.


5

Als Sprachdesigner möchte ich einige der anderen Antworten hier wiederholen, sie aber mit den Augen von jemandem zur Verfügung stellen, der eine Sprache aufbaut.

Eine API ist noch nicht fertig, wenn Sie alles hinzugefügt haben, was Sie können. Eine API ist fertig, wenn Sie alles getan haben, was Sie können.

Eine Programmiersprache muss in einer Sprache angegeben werden. Sie müssen in der Lage sein, die Bedeutung eines in Ihrer Sprache geschriebenen Programms zu vermitteln. Diese Sprache ist sehr schwer zu schreiben und noch schwerer gut zu schreiben. Im Allgemeinen ist es eine sehr präzise und gut strukturierte Form des Englischen, die verwendet wird, um nicht dem Computer, sondern anderen Entwicklern, insbesondere den Entwicklern, die Compiler oder Interpreten für Ihre Sprache schreiben, Bedeutung zu vermitteln. Hier ist ein Beispiel aus der C ++ 11-Spezifikation [intro.multithread / 14]:

Die sichtbare Folge von Nebenwirkungen auf ein atomares Objekt M in Bezug auf eine Werteberechnung B von M ist eine maximal zusammenhängende Teilfolge von Nebenwirkungen in der Modifikationsreihenfolge von M, wobei die erste Nebenwirkung in Bezug auf B sichtbar ist und für jede Nebenwirkung ist es nicht der Fall, dass B davor auftritt. Der Wert eines atomaren Objekts M, wie er durch die Bewertung B bestimmt wird, ist der Wert, der durch eine Operation in der sichtbaren Folge von M in Bezug auf B gespeichert wird. [Anmerkung: Es kann gezeigt werden, dass die sichtbare Folge von Nebenwirkungen eines Werts ist Die Berechnung ist aufgrund der folgenden Kohärenzanforderungen einzigartig. —Ende Notiz]

Blek! Jeder, der es verstanden hat, wie C ++ 11 mit Multithreading umgeht, kann verstehen, warum der Wortlaut so undurchsichtig sein muss, aber das verzeiht nicht, dass er ... na ja ... so undurchsichtig ist!

Vergleichen Sie dies mit der Definition von std::shared_ptr<T>::resetim Abschnitt Bibliothek des Standards:

template <class Y> void reset(Y* p);

Effekte: Entsprichtshared_ptr(p).swap(*this)

Was ist der Unterschied? Im Sprachdefinitionsteil können die Autoren nicht davon ausgehen, dass der Leser die Sprachprimitive versteht. Alles muss sorgfältig in englischer Prosa angegeben werden. Sobald wir den Bibliotheksdefinitionsteil erreicht haben, können wir die Sprache verwenden, um das Verhalten festzulegen. Das ist oft viel einfacher!

Grundsätzlich könnte man zu Beginn des Spezifikationsdokuments einen reibungslosen Aufbau von Grundelementen erreichen, indem man definiert, was wir als "Standardbibliotheksfunktionen" betrachten, ohne eine Grenze zwischen "Sprachgrundelementen" und "Standardbibliotheksfunktionen" ziehen zu müssen "Standard Library" -Funktionen. In der Praxis erweist sich das Zeichnen dieser Linie als äußerst wertvoll, da Sie damit einige der komplexesten Teile der Sprache (z. B. diejenigen, die Algorithmen implementieren müssen) in einer Sprache schreiben können, die sie ausdrücken soll.

Und wir sehen tatsächlich einige verschwommene Linien:

  • In Java java.lang.ref.Reference<T>kann es nur von den Standardbibliotheksklassen untergeordnet werden, java.lang.ref.WeakReference<T> java.lang.ref.SoftReference<T>und java.lang.ref.PhantomReference<T>weil das Verhalten von Referenceso stark mit der Java-Sprachspezifikation verflochten ist, dass sie einige Einschränkungen für den als "Standardbibliotheksklassen" implementierten Teil dieses Prozesses erforderlich machen.
  • In C # gibt es eine Klasse namens System.Delegate, die das Konzept von Delegaten kapselt. Trotz seines Namens ist es kein Delegierter. Es ist auch eine abstrakte Klasse (kann nicht instanziiert werden), aus der Sie keine abgeleiteten Klassen erstellen können. Nur das System kann dies durch Funktionen tun, die in der Sprachspezifikation geschrieben sind.

2

Dies ist als Ergänzung zu den vorhandenen Antworten gedacht (und für einen Kommentar zu lang).

Es gibt mindestens zwei weitere Gründe für eine Standardbibliothek:

Zutrittsschranke

Wenn sich ein bestimmtes Sprachmerkmal in einer Bibliotheksfunktion befindet und ich wissen möchte, wie es funktioniert, kann ich einfach die Quelle für diese Funktion lesen. Wenn ich einen Fehlerbericht / Patch / Pull-Antrag einreichen möchte, ist es im Allgemeinen nicht zu schwierig, einen Fix und Testfall (e) zu codieren. Wenn es im Compiler ist, muss ich in der Lage sein, in die Interna zu graben. Selbst wenn der Compiler in derselben Sprache geschrieben ist (und dies sollte auch so sein), ist er kein Anwendungscode. Es kann ewig dauern, bis die richtigen Dateien gefunden sind.

Sie können sich von vielen potenziellen Mitwirkenden abkoppeln, wenn Sie diesen Weg gehen.

Hot Code wird geladen

Viele Sprachen bieten diese Funktion bis zu einem gewissen Grad an, aber es wäre enorm kompliziert, den Code, der das Hot-Reload ausführt, im laufenden Betrieb neu zu laden. Wenn der SL von der Laufzeit getrennt ist, kann er neu geladen werden.


3
"Jeder sich selbst respektierende Compiler sollte sich selbst hosten" - überhaupt nicht. Es wäre sinnlos, Versionen von say LLVM in C, C ++, Objective-C, Swift, Fortran usw. schreiben zu lassen, um alle diese Sprachen zu kompilieren.
gnasher729

@ gnasher729 ist das nicht ein besonderer Fall (zusammen mit anderen mehrsprachigen Zielen wie der CLR)?
Jared Smith

@JaredSmith Ich würde sagen, es ist jetzt der allgemeine Fall, überhaupt nicht speziell. Niemand schreibt mehr "einen Compiler" als monolithische Anwendung. Sie produzieren stattdessen Compilersysteme . Der größte Teil der Funktionalität des vollständigen Compilers ist völlig unabhängig von der jeweiligen zu kompilierenden Sprache, und ein Großteil des sprachabhängigen Teils kann durch die Angabe verschiedener Daten zur Definition der Grammatik der Sprache erfolgen, nicht durch das Schreiben eines anderen Codes für jede Sprache, die Sie verwenden kompilieren wollen.
Alephzero

2

Dies ist eine interessante Frage, aber es gibt bereits viele gute Antworten, daher werde ich nicht versuchen, eine vollständige zu beantworten.

Zwei Dinge, von denen ich glaube, dass sie nicht genug Beachtung finden:

Erstens ist das Ganze nicht super übersichtlich. Es ist ein bisschen wie ein Spektrum, weil es Gründe gibt, die Dinge anders zu machen. Beispielsweise kennen Compiler häufig Standardbibliotheken und ihre Funktionen. Beispiel für das Beispiel: Cs "Hello World" -Funktion - printf - ist die beste, die ich mir vorstellen kann. Es ist eine Bibliotheksfunktion, das muss eine Art sein, da es sehr plattformabhängig ist. Das Verhalten (Implementierung definiert) muss dem Compiler jedoch bekannt sein, um den Programmierer vor fehlerhaften Aufrufen zu warnen. Dies ist nicht besonders ordentlich, wurde aber als guter Kompromiss angesehen. Dies ist übrigens die eigentliche Antwort auf die meisten Fragen zum "Warum dieses Design": viel Kompromiss und "schien zu dieser Zeit eine gute Idee zu sein". Nicht immer das "das war der klare Weg, es zu tun" oder "

Zweitens erlaubt es der Standardbibliothek, nicht der ganze Standard zu sein. Es gibt viele Situationen, in denen eine Sprache wünschenswert ist, aber die Standardbibliotheken, die sie normalerweise begleiten, sind nicht sowohl praktisch als auch wünschenswert. Dies ist am häufigsten bei Systemprogrammiersprachen wie C auf nicht standardmäßigen Plattformen der Fall. Wenn Sie beispielsweise ein System ohne Betriebssystem oder Scheduler haben, wird kein Threading durchgeführt.

Mit einem Standardbibliotheksmodell (und dem darin unterstützten Threading) kann dies sauber gehandhabt werden: Der Compiler ist ziemlich gleich, Sie können die Bits der zutreffenden Bibliotheken wiederverwenden und alles, was Sie nicht entfernen können. Wenn dies in den Compiler eingebrannt wird, wird es unordentlich.

Beispielsweise:

  • Sie können kein kompatibler Compiler sein.

  • Wie würden Sie Ihre Abweichung vom Standard angeben? Beachten Sie, dass es normalerweise eine Form der Import- / Include-Syntax gibt, bei der ein Fehler auftreten kann, z. B. der Pythons-Import oder das C-Include, die leicht auf das Problem hinweisen, wenn im Standardbibliotheksmodell etwas fehlt.

Ähnliche Probleme treten auch auf, wenn Sie die Bibliotheksfunktionalität optimieren oder erweitern möchten. Dies ist weitaus häufiger als Sie vielleicht denken. Nur um beim Threading zu bleiben: Windows, Linux und einige-exotische-Netzwerk-Prozessor-Einheiten machen das Threading ganz anders. Während die Linux / Windows-Bits möglicherweise ziemlich statisch sind und eine identische API verwenden können, ändert sich das NPU-Zeug mit dem Wochentag und die API mit dieser. Compiler würden schnell davon abweichen, wenn die Leute entschieden, welche Bits sie brauchen, um zu unterstützen / schnell auszusteigen, wenn es keine Möglichkeit gäbe, solche Dinge aufzuteilen.

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.