Typ System
Im Informatik, im Speziellen Programmiersprachen, a Typ System ist ein logisches System bestehend aus einer Reihe von Regeln, die eine Eigenschaft namens a zuweisen Typ zu jedem "Begriff", normalerweise die verschiedenen Konstrukte von a Computer Programm, wie zum Beispiel Variablen, Ausdrücke, Funktionen oder Module.[1] Ein Typsystem bestimmt die Vorgänge, die mit einem Begriff und für Variablen die möglichen Werte ersetzt werden können. Geben Sie die Systeme ein, die die ansonsten impliziten Kategorien formalisieren und durchsetzen, für den der Programmierer verwendet wird Algebraische Datentypen, Datenstrukturen oder andere Komponenten (z. B. "String", "Array of Float", "Funktion return boolean").
Typsysteme werden häufig als Teil von angegeben Programmiersprachen und in Dolmetscher und Compiler eingebaut, obwohl das Typsystem einer Sprache durch erweitert werden kann Optionale Werkzeuge Dadurch wurden zusätzliche Überprüfungen mit der ursprünglichen Syntax und Grammatik der Sprache durchgeführt. Der Hauptzweck eines Typsystems in einer Programmiersprache besteht darin, die Möglichkeiten für die Verringerung der Möglichkeiten für Käfer in Computerprogrammen, insbesondere beweisen, dass nein Geben Sie Fehler ein kann auftreten.[2] Das betreffende Typsystem bestimmt, was einen Typfehler ausmacht. Im Allgemeinen ist es jedoch, zu verhindern, dass Operationen erwarten, dass eine bestimmte Art von Wert mit Werten verwendet wird, für die dieser Betrieb keinen Sinn macht (Gültigkeitsfehler). Typsysteme ermöglichen die Definition Schnittstellen zwischen verschiedenen Teilen eines Computerprogramms und dann überprüfen, ob die Teile konsistent angeschlossen wurden. Diese Überprüfung kann statisch auftreten (bei Zeit kompilieren), dynamisch (bei Laufzeit) oder als Kombination aus beiden. Typsysteme haben auch andere Ziel Compiler -Optimierungen, erlauben für Mehrfachversandund Bereitstellung einer Form der Dokumentation.
Verwendungsübersicht
Ein Beispiel für ein einfaches Typsystem ist das der der C Sprache. Die Teile eines C -Programms sind die Funktion Definitionen. Eine Funktion wird von einer anderen Funktion aufgerufen. Die Schnittstelle einer Funktion gibt den Namen der Funktion und eine Liste von Parametern an, die an den Code der Funktion übergeben werden. Der Code einer aufgerufenen Funktion gibt den Namen des aufgerufenen sowie die Namen von Variablen an, die Werte für die Übergabe an ihn enthalten. Während der Ausführung werden die Werte in einen temporären Speicher eingelegt, dann springt die Ausführung zum Code der aufgerufenen Funktion. Der Code der aufgerufenen Funktion greift auf die Werte zu und nutzt sie. Wenn die Anweisungen innerhalb der Funktion mit der Annahme geschrieben werden, eine zu erhalten ganze Zahl Wert, aber der aufrufende Code hat a bestanden Schwimmpunktwertund dann wird das falsche Ergebnis von der aufgerufenen Funktion berechnet. Der C -Compiler überprüft die Argumente der Argumente, die an eine Funktion übergeben wurden, wenn sie gegen die in der Definition der Funktion deklarierten Parameter aufgerufen werden. Wenn die Typen nicht übereinstimmen, wirft der Compiler einen Kompilierungszeitfehler aus.
A Compiler Kann auch den statischen Wert eines Werts verwenden, um den von ihm benötigten Speicher und die Auswahl der Algorithmen für den Wert des Werts zu optimieren. In vielen C Compiler die schweben Datentypzum Beispiel ist in 32 dargestellt Bits, in Übereinstimmung mit dem IEEE-Spezifikation für schwimmende Punktzahlen mit einer Präzision. Sie werden somit schwimmende Punktspezifische verwenden Mikroprozessoroperationen auf diesen Werten (Floating-Punkt-Addition, Multiplikation usw.).
Die Tiefe der Typeinschränkungen und die Art ihrer Bewertung beeinflussen die Typisierung der Sprache. EIN Programmiersprache kann einen Betrieb mit verschiedenen Auflösungen für jeden Typ im Fall von weiter assoziieren Typ Polymorphismus. Typentheorie ist die Untersuchung von Typsystemen. Die konkreten Arten einiger Programmiersprachen wie Ganzzahlen und Zeichenfolgen hängen von praktischen Fragen der Computerarchitektur, der Compiler -Implementierung und des Sprachdesigns ab.
Grundlagen
Formal, Typentheorie Studientypsysteme. Eine Programmiersprache muss die Möglichkeit haben, die Überprüfung mit dem zu tippen Typ System Ob zur Kompilierzeit oder zur Laufzeit, manuell kommentiert oder automatisch abgeleitet. Wie Mark Manasse es präzise ausdrückte:[3]
Das grundlegende Problem, das von einer Typtheorie behandelt wird, besteht darin, sicherzustellen, dass Programme eine Bedeutung haben. Das durch eine Typtheorie verursachte grundlegende Problem ist, dass aussagekräftige Programme möglicherweise keine ihnen zugeschriebenen Bedeutungen haben. Die Suche nach reicheren Typsystemen resultiert aus dieser Spannung.
Zuweisen eines Datentyps, der bezeichnet wird Typisierung, gibt einer Sequenz von Bedeutung Bits wie ein Wert in Erinnerung oder einige Objekt so wie ein Variable. Die Hardware von a Allzweckcomputer kann nicht zwischen a diskriminieren Speicheradresse und ein Anweisungscode, oder zwischen a Charakter, ein ganze Zahl, oder ein Schwimmpunktzahl, weil es keine intrinsische Unterscheidung zwischen den möglichen Werten macht, die eine Abfolge von Bits könnte bedeuten.[Anmerkung 1] Assoziieren Sie eine Abfolge von Bits mit einem Typ, das der programmierbaren Hardware zur Bildung a ist, um a zu bilden Symbolisches System besteht aus dieser Hardware und einem Programm.
Ein Programm assoziiert jeden Wert mit mindestens einem bestimmten Typ, kann aber auch auftreten, dass ein Wert mit vielen verbunden ist Subtypen. Andere Einheiten, wie z. Objekte, Module, Kommunikationskanäle und Abhängigkeiten kann mit einem Typ verbunden werden. Sogar ein Typ kann mit einem Typ verbunden werden. Eine Implementierung von a Typ System Könnte theoretisch assoziierte Identifikationen genannt Datentyp (eine Art von Wert), Klasse (eine Art eines Objekts) und nett (a Typ eines Typs, oder Metatyp). Dies sind die Abstraktionen, die das Tippen durchlaufen kann, auf einer Hierarchie von in einem System enthaltenen Ebenen.
Wenn eine Programmiersprache ein aufwändigeres Typsystem entwickelt, erhält sie einen feinkörnigeren Regelsatz als die grundlegende Typprüfung. Dies ist jedoch zu einem Preis, wenn die Typ -Schlussfolgerungen (und andere Eigenschaften) werden unentscheidbarund wenn der Programmierer mehr Aufmerksamkeit für den Anmerkungscode oder die Berücksichtigung von computerbezogenen Vorgängen und Funktionen geschenkt werden muss. Es ist schwierig, ein ausreichend ausdrucksstarkes Typsystem zu finden, das alle Programmierpraktiken in a entspricht Geben Sie sicher Benehmen.
Ein Programmiersprache Compiler kann auch a implementieren abhängiger Typ oder an EffektsystemDies ermöglicht es noch mehr Programmspezifikationen, von einem Typ -Checker zu überprüft. Über einfache Wertschöpfungspaare hinaus ist eine virtuelle "Region" von Code "einer" Effekt "-Komponente zugeordnet, die beschreibt was wird erledigt mit wasund ermöglichen, zum Beispiel einen Fehlerbericht zu "werfen". Somit kann das symbolische System a sein Typ -and -Effect -System, was es mit mehr Sicherheitsprüfungen ausschöpft als die Typ -Überprüfung allein.
Unabhängig davon, ob der Compiler automatisiert oder von einem Programmierer angegeben ist, macht ein Typsystem das Programmverhalten illegal, wenn es außerhalb der Regeln des Typ-Systems ist. Zu den Vorteilen, die von Programmierern angegebene Typsysteme bereitgestellt werden, gehören:
- Abstraktion (oder Modularität)-Typen ermöglichen es den Programmierern, auf einem höheren Niveau als das Bit oder das Byte zu denken und sich nicht mit niedriger Implementierung zu beschäftigen. Beispielsweise können Programmierer eine Zeichenfolge als eine Reihe von Zeichenwerten anstatt als bloßes Array von Bytes vorstellen. Höher noch, Typen ermöglichen es den Programmierern, darüber nachzudenken und auszudrücken Schnittstellen zwischen zwei von irgendein-Scharme Subsysteme. Dies ermöglicht mehr Lokalisierungsstufen, so dass die für die Interoperabilität der Subsysteme erforderlichen Definitionen konsistent bleiben, wenn diese beiden Subsysteme kommunizieren.
- Dokumentation - In expressiven Typsystemen können Typen als Form von dienen Dokumentation Klärung der Absicht des Programmierers. Wenn ein Programmierer beispielsweise eine Funktion als Rückgabe eines Zeitstempelstyps deklariert, dokumentiert diese Funktion, wenn der Zeitstempeltyp explizit im Code als Ganzzahltyp deklariert werden kann.
Zu den von Compiler spezifizierten Typsystemen bereitgestellten Vorteile gehören:
- Optimierung -Statische Typ-Überprüfung kann nützliche Informationen zur Kompilierung bieten. Wenn ein Typ beispielsweise erfordert, dass ein Wert im Speicher an einem mehreren von vier Bytes ausgerichtet ist, kann der Compiler möglicherweise effizientere Maschinenanweisungen verwenden.
- Sicherheit - Ein Typsystem ermöglicht dem Compiler um bedeutungslose oder ungültige Code zu erkennen. Zum Beispiel können wir einen Ausdruck identifizieren
3 / "Hallo, Welt"
als ungültig, wenn die Regeln nicht angeben ganze Zahl durch eine Saite. Starke Typisierung bietet mehr Sicherheit, kann aber nicht vollständig garantieren Geben Sie Sicherheit ein.
Geben Sie Fehler ein
Ein Typfehler ist ein unbeabsichtigter Zustand[Klarstellung erforderlich] Dies könnte sich in mehreren Phasen der Entwicklung eines Programms manifestieren. Somit wird im Typsystem eine Einrichtung zur Erkennung des Fehlers benötigt. In einigen Sprachen wie Haskell, für die Geben Sie Inferenz ein ist automatisiert, Fussel könnte seinem Compiler zur Verfügung stehen, um die Fehlererkennung zu unterstützen.
Type Sicherheit trägt bei Programm Korrektheit, aber möglicherweise nur die Korrektheit auf Kosten des Typs garantieren, das sich selbst überprüft hat unentschlossenes Problem. In einem Typ System Bei automatisiertem Typ, das ein Programm prüft, kann sich nachweisen, dass er falsch ausgeführt wird und jedoch keine Compiler -Fehler erzeugt. Durch Null teilen ist eine unsichere und falsche Operation, aber ein Typ -Checker, der ausgeführt wird Zeit kompilieren scannt in den meisten Sprachen nur nicht nach Null, und dann bleibt es als a Laufzeit Fehler. Das Fehlen dieser Defekte zu beweisen, andere Arten von Formale Methodenkollektiv als bekannt als Programmanalysen, werden gemeinsam verwendet. Alternativ kann ein ausreichend ausdrucksstarkes Typsystem, wie in abhängigen Sprachen, diese Art von Fehlern verhindern (z. B. Expressions die Art der ungleich Null-Zahlen). Zusätzlich Softwaretest ist ein empirisch Methode zum Auffinden von Fehlern, die der Typ Checker nicht erkennen kann.
Geben Sie die Überprüfung ein
Der Prozess der Überprüfung und Durchsetzung der Einschränkungen von Typen -Geben Sie die Überprüfung ein- Möglicherweise treten bei Zeit kompilieren (eine statische Überprüfung) oder bei Laufzeit. Wenn eine Sprachspezifikation ihre Schreibregeln stark erfordert (d. H. Mehr oder weniger, nur die automatischen zuzulassen Geben Sie Conversions ein die keine Informationen verlieren), kann man den Prozess als bezeichnen stark tippt, wenn nicht, als schwach tippt. Die Begriffe werden normalerweise nicht in einem strengen Sinne verwendet.
Statische Typprüfung
Statische Typprüfung ist der Prozess der Überprüfung der Geben Sie Sicherheit ein eines Programms basierend auf der Analyse des Textes (Text eines Programms (Quellcode). Wenn ein Programm einen statischen Typ Checker übergeht, wird das Programm garantiert einige festgelegte Sicherheitseigenschaften für alle möglichen Eingaben erfüllen.
Statische Typprüfung kann als begrenzte Form von betrachtet werden Programmüberprüfung (sehen Geben Sie Sicherheit ein) und in einer Typ-sicherer Sprache kann auch als Optimierung angesehen werden. Wenn ein Compiler beweisen kann, dass ein Programm gut getroffen ist, muss es keine dynamischen Sicherheitskontrollen abgeben, sodass das resultierende zusammengezeigte Binär schneller und kleiner wird.
Statische Typprüfung auf Turing-Complete Sprachen sind von Natur aus konservativ. Das heißt, wenn ein Typsystem beides ist Klang (was bedeutet, dass es alle falschen Programme ablehnt) und entschlossen (Dies bedeutet, dass es möglich ist, einen Algorithmus zu schreiben, der feststellt unvollständig (Dies bedeutet, dass es korrekte Programme gibt, die ebenfalls abgelehnt werden, obwohl sie keine Laufzeitfehler treffen).[4] Betrachten Sie beispielsweise ein Programm mit dem Code:
wenn
dann anders
Auch wenn der Ausdruck
Bewertet immer zu Stimmt
Zur Laufzeit lehnen die meisten Typ-Checkers das Programm als schlecht ab, da es für einen statischen Analysator schwierig ist (wenn nicht unmöglich), zu bestimmen, dass die anders
Zweig wird nicht genommen.[5] Infolgedessen erkennt ein statischer Typ Checker schnell Typfehler in selten verwendeten Codepfaden. Ohne statische Typprüfung sogar Codeabdeckung Tests mit 100% Abdeckung können solche Typfehler möglicherweise nicht finden. Die Tests können solche Typfehler nicht erkennen, da die Kombination aller Orte, an denen Werte erstellt werden, und an allen Orten, an denen ein bestimmter Wert verwendet wird, berücksichtigt werden muss.
Eine Reihe nützlicher und gemeinsamer Programmiersprachenfunktionen können nicht statisch überprüft werden, wie z. Niederschlag. So haben viele Sprachen sowohl eine statische als auch dynamische Typprüfung. Der statische Typ Checker überprüft, was er kann, und dynamische Überprüfungen überprüfen den Rest.
Viele Sprachen mit statischer Überprüfung bieten eine Möglichkeit, den Typ -Checker zu umgehen. Einige Sprachen ermöglichen es den Programmierern, zwischen statischer und dynamischer Sicherheit zu wählen. Zum Beispiel, C# unterscheidet zwischen statisch typiert und dynamisch typisch Variablen. Die Verwendung der ersteren werden statisch überprüft, während die Verwendungen der letzteren dynamisch überprüft werden. Andere Sprachen erlauben das Schreiben von Code, der nicht vom Typ Typ ist. Zum Beispiel in C, Programmierer können einen Wert zwischen zwei beliebigen Typen mit derselben Größe frei aufnehmen und das Typ -Konzept effektiv untergraben.
Eine Liste von Sprachen mit statischer Typüberprüfung finden Sie in der Kategorie für statisch typische Sprachen.
Dynamische Informationen zum Überprüfen und Laufzeittypen
Dynamische Typüberprüfung ist der Prozess der Überprüfung der Art eines Programms zur Laufzeit. Implementierungen von dynamisch typprüften Sprachen assoziieren im Allgemeinen jedes Laufzeitobjekt mit a Typ -Tag (d. H. Ein Verweis auf einen Typ) mit seinen Typinformationen. Diese Laufzeittypinformationen (RTTI) können auch zur Implementierung verwendet werden Dynamischer Versand, späte Bindung, Niederschlag, Betrachtungund ähnliche Merkmale.
Die meisten Typ-sicheren Sprachen enthalten eine Form der dynamischen Typüberprüfung, auch wenn sie auch einen statischen Typ-Checker haben. [6] Der Grund dafür ist, dass viele nützliche Merkmale oder Eigenschaften schwierig oder unmöglich sind, statisch zu überprüfen. Nehmen wir beispielsweise an, dass ein Programm zwei Typen definiert, A und B, wobei B ein Subtyp von A ist, wenn das Programm versucht, einen Wert vom Typ A in Typ B zu konvertieren, der als bekannt ist NiederschlagDann ist die Operation nur dann legal, wenn der zu konvertierte Wert tatsächlich ein Wert von Typ B ist. Somit ist eine dynamische Prüfung erforderlich, um zu überprüfen, ob die Operation sicher ist. Diese Anforderung ist einer der Kritikpunkte des Downcasting.
Per Definition kann eine dynamische Überprüfung des Typs dazu führen, dass ein Programm zur Laufzeit fehlschlägt. In einigen Programmiersprachen ist es möglich, diese Fehler zu antizipieren und sich von ihm zu erholen. In anderen Fällen werden Typenprüfungsfehler als tödlich angesehen.
Programmiersprachen, die dynamische Überprüfung des Typs, aber keine statische Typüberprüfung enthalten, werden häufig als "dynamisch-typische Programmiersprachen" bezeichnet. Eine Liste solcher Sprachen finden Sie in der Kategorie für dynamisch typische Programmiersprachen.
Kombination der statischen und dynamischen Typprüfung
Einige Sprachen ermöglichen sowohl eine statische als auch dynamische Typisierung. Zum Beispiel unterstützen Java und einige andere angeblich statisch typische Sprachen Unterstützung Niederschlag Typen zu ihren SubtypenAbfragen eines Objekts, um den dynamischen Typ und andere Typvorgänge zu ermitteln, die von Informationen zum Laufzeittyp abhängen. Ein anderes Beispiel ist C ++ RTTI. Im Allgemeinen enthalten die meisten Programmiersprachen Mechanismen zum Versenden von verschiedenen "Daten", wie z. Disjunkte Gewerkschaften, Laufzeitpolymorphismus, und Variantentypen. Selbst wenn sie nicht mit Typ -Anmerkungen oder Typprüfungen interagieren, ähneln solche Mechanismen den dynamischen Typisierungsimplementierungen wesentlich. Sehen Programmiersprache Weitere Diskussionen der Wechselwirkungen zwischen statischer und dynamischer Typisierung.
Objekte in objektorientierten Sprachen werden normalerweise durch eine Referenz zugegriffen, deren statischer Zieltyp (oder Manifesttyp) entweder dem Laufzeittyp des Objekts (dessen latenter Typ) oder einem Supertypen davon entspricht. Dies ist mit dem übereinstimmend Liskov -Substitutionsprinzip, was besagt, dass alle Operationen, die an einer Instanz eines bestimmten Typs ausgeführt werden, auch an einer Instanz eines Subtyps durchgeführt werden können. Dieses Konzept wird auch als Subsumsum bezeichnet oder Subtyp -Polymorphismus. In einigen Sprachen können auch Subtypen besitzen Kovariante oder kontravariante Rückgabetypen bzw. Argumententypen.
Zum Beispiel bestimmte Sprachen Clojure, Common Lisp, oder Cython werden standardmäßig dynamisch überprüft, aber ermöglichen es den Programmen, sich in statische Typprüfungen zu entscheiden, indem Sie optionale Anmerkungen bereitstellen. Ein Grund, solche Hinweise zu verwenden, wäre die Optimierung der Leistung kritischer Abschnitte eines Programms. Dies wird formalisiert von schrittweise Typisierung. Die Programmierumgebung Drracket, eine pädagogische Umgebung, die auf Lisp und einem Vorläufer der Sprache basiert Schläger ist auch weichtyp.[7]
Umgekehrt bietet die C# -Sprache nach Version 4.0 eine Möglichkeit, anzugeben, dass eine Variable nicht statisch überprüft werden sollte. Eine Variable, deren Typ ist dynamisch
unterliegt nicht einer statischen Überprüfung des Typs. Stattdessen stützt sich das Programm auf Informationen zum Laufzeittyp, um festzustellen, wie die Variable verwendet werden kann.[8]
Im Rost, das dyn std::any::Any
Typ bietet eine dynamische Eingabe von 'static
Typen.[9]
Statische und dynamische Typprüfung in der Praxis
Die Wahl zwischen statischer und dynamischer Typisierung erfordert bestimmte Kompromisse.
Die statische Eingabe kann zum Kompilierungszeit zuverlässig Typfehler finden, was die Zuverlässigkeit des gelieferten Programms erhöht. Programmierer sind jedoch nicht einverstanden, wie häufig Typfehler auftreten, was zu weiteren Meinungsverschiedenheiten über den Anteil der kodierten Fehler führt, die durch die angemessene Darstellung der entworfenen Codetypen gefangen würden.[10][11] Statische Typisierungsanwälte[wer?] Glauben Sie glauben, dass Programme zuverlässiger sind, wenn sie gut überprüft wurden, während dynamische Befürworter der Dynamik[wer?] Zeigen Sie auf verteilten Code, der sich als zuverlässig und auf kleine Fehlerdatenbanken erwiesen hat. Der Wert der statischen Typisierung nimmt zu, wenn die Stärke des Typsystems erhöht wird. Befürworter von Abhängige Typisierung,[wer?] implementiert in Sprachen wie z. Abhängig ml und Epigramm, haben vorgeschlagen, dass fast alle Fehler als Typfehler betrachtet werden können, wenn die in einem Programm verwendeten Typen vom Programmierer ordnungsgemäß deklariert oder vom Compiler korrekt abgeleitet werden.[12]
Die statische Typisierung führt normalerweise zu kompilierten Code, der schneller ausgeführt wird. Wenn der Compiler die genauen Datentypen kennt, die verwendet werden (was für die statische Überprüfung erforderlich ist, entweder durch Deklaration oder Inferenz), kann er einen optimierten Maschinencode erzeugen. Einige dynamisch typische Sprachen wie z. Common Lisp Ermöglichen Sie aus diesem Grund optionale Typdeklarationen für die Optimierung.
Im Gegensatz dazu kann die dynamische Tippen es Compilern ermöglichen, schneller zu laufen und Dolmetscher So dynamisch neuer Code laden, da Änderungen des Quellcodes in dynamisch-typen Sprachen möglicherweise zu einer geringeren Überprüfung der Durchführung und weniger Code zum Nachdenken führen.[Klarstellung erforderlich] Auch dies kann den Zyklus für den Kompilieren von Bearbeitungs-Test-Tests verringern.
Statisch getotische Sprachen, die mangeln Geben Sie Inferenz ein (wie zum Beispiel C und Java vor Version 10) Fordern Sie, dass Programmierer die Typen deklarieren, die eine Methode oder Funktion verwenden muss. Dies kann als zusätzliche Programmdokumentation dienen, die aktiv und dynamisch anstelle von statischer Produkte sind. Dies ermöglicht es einem Compiler, zu verhindern, dass er aus der Synchronisation abfällt und von den Programmierern ignoriert wird. Eine Sprache kann jedoch statisch getippt werden, ohne dass Typdeklarationen erforderlich sind (Beispiele enthalten Haskell, Scala, Ocaml, F#und in geringerem Maße C# und C ++), so dass eine explizite Typdeklaration keine erforderliche Anforderung für die statische Eingabe in allen Sprachen ist.
Durch die dynamische Eingabe werden Konstrukte ermöglicht, die einige (einfache) statische Typprüfung als illegal ablehnen würden. Zum Beispiel, bewerten Funktionen, die beliebige Daten als Code ausführen, werden möglich. Ein bewerten Funktion ist mit statischer Typisierung möglich, erfordert jedoch eine erweiterte Verwendung von Algebraische Datentypen. Darüber hinaus berücksichtigt die dynamische Typisierung den Übergangscode und Prototyping besser, z. B. die Erlaubnis einer Platzhalterdatenstruktur (Scheinobjekt) transparent anstelle einer vollständigen Datenstruktur verwendet werden (normalerweise zum Zwecke des Experimentierens und der Prüfung).
Das dynamische Tippen ermöglicht normalerweise Ententypisierung (das ermöglicht Einfachere Code -Wiederverwendung). Viele[angeben] Sprachen mit statischer Tippen sind auch vorhanden Ententypisierung oder andere Mechanismen wie generische Programmierung Dies ermöglicht auch eine leichtere Wiederverwendung von Code.
Das dynamische Typing macht normalerweise Metaprogrammierung einfacher zu bedienen. Zum Beispiel, C ++ - Vorlagen sind in der Regel umständlicher zu schreiben als das Äquivalent Rubin oder Python Code seit C ++ hat stärkere Regeln für Typdefinitionen (sowohl für Funktionen als auch für Variablen). Dies zwingt einen Entwickler, mehr zu schreiben Boilerplate -Code für eine Vorlage als ein Python -Entwickler müsste es tun. Fortgeschrittenere Laufzeitkonstrukte wie z. Metaklasse und Selbstbeobachtung sind oft schwerer in den statisch typischen Sprachen zu verwenden. In einigen Sprachen können solche Merkmale auch verwendet werden, z. Um neue Typen und Verhaltensweisen im laufenden Fliegen zu generieren, basierend auf Laufzeitdaten. Solche fortgeschrittenen Konstrukte werden häufig von bereitgestellt von Dynamische Programmiersprachen; Viele davon werden dynamisch getippt Dynamisches Typing muss nicht in Verbindung gebracht werden mit Dynamische Programmiersprachen.
Starke und schwache Typsysteme
Sprachen werden oft umgangssprachlich als als bezeichnet stark tippt oder schwach tippt. Tatsächlich gibt es keine allgemein akzeptierte Definition dessen, was diese Begriffe bedeuten. Im Allgemeinen gibt es genauere Begriffe, die die Unterschiede zwischen Typsystemen darstellen, die Menschen dazu bringen, sie "stark" oder "schwach" zu bezeichnen.
Geben Sie Sicherheit und Speichersicherheit ein
Eine dritte Möglichkeit, das Typsystem einer Programmiersprache zu kategorisieren, besteht in der Sicherheit typisierter Vorgänge und Conversions. Informatiker verwenden den Begriff Typ-sicherer Sprache Beschreibung von Sprachen, die keine Operationen oder Konvertierungen zulassen, die gegen die Regeln des Typsystems verstoßen.
Informatiker verwenden den Begriff Gedächtnisfeste Sprache (oder nur sichere Sprache) Beschreibung von Sprachen, die nicht zulassen, dass Programme auf Speicher zugreifen, die nicht für ihre Verwendung zugewiesen wurden. Zum Beispiel wird eine mememschutzsichere Sprache Überprüfen Sie die Array -Grenzenoder statisch garantieren (d. H. Zum Kompilieren der Zeit vor der Ausführung), dass Array aus den Array-Grenzen zugreift, die Kompilierzeit- und möglicherweise Laufzeitfehler.
Betrachten Sie das folgende Programm einer Sprache, die sowohl Typ-Sicherheit als auch Speichersicher ist:[13]
var x: = 5; var y: = "37"; var z: = x + y;
In diesem Beispiel die Variable z
Wird den Wert 42 haben. Obwohl dies möglicherweise nicht das ist, was der Programmierer erwartet hat, ist er ein genau definiertes Ergebnis. Wenn y
Wären eine andere Zeichenfolge, die nicht in eine Zahl (z. B. "Hallo Welt") konvertiert werden konnte, wäre das Ergebnis ebenfalls gut definiert. Beachten Sie, dass ein Programm Type-Sicherheit oder Speichersicherheit sein kann und dennoch bei einem ungültigen Vorgang abstürzt. Dies gilt für Sprachen, in denen das Typsystem nicht ausreichend fortgeschritten ist, um die Gültigkeit von Operationen für alle möglichen Operanden genau anzugeben. Wenn ein Programm jedoch auf eine Operation trifft, die nicht vom Typ Typ ist, ist die Beendigung des Programms häufig die einzige Option.
Betrachten Sie nun ein ähnliches Beispiel in C:
int x = 5; verkohlen y[] = "37"; verkohlen* z = x + y; printf("%c\n", *z);
In diesem Beispiel z
verweist auf eine Speicheradresse fünf Zeichen darüber hinaus y
äquivalent zu drei Zeichen nach dem terminierenden Zero -Zeichen der Zeichenfolge, auf das hingewiesen wurde y
. Dies ist Speicher, auf den das Programm nicht erwartet wird. In C -Begriffen ist dies einfach undefiniertes Verhalten und das Programm kann alles tun; Mit einem einfachen Compiler könnte es tatsächlich je nach Byte nach der Zeichenfolge "37" gespeichert werden. Wie dieses Beispiel zeigt, ist C nicht maßstabssicher. Da willkürliche Daten als Zeichen angenommen wurden, handelt es sich auch um eine Typ-Sicherheit-Sprache.
Im Allgemeinen gehen Typ-Safety und Memory-Safety in Hand in Hand. Beispielsweise ist eine Sprache, die Zeiger-Arithmetik- und Number-zu-Zeiger-Konvertierungen (wie c) unterstützt, weder Speichersicherheit noch Typ-Safe, da ein beliebiger Speicher so zugänglich ist, als wäre es gültiger Speicher eines beliebigen Typs.
Weitere Informationen finden Sie unter Speichersicherheit.
Variable Ebenen der Typprüfung
Einige Sprachen ermöglichen verschiedene Ebenen der Überprüfung, um sich für verschiedene Coderegionen zu bewerben. Beispiele beinhalten:
- Das
Verwenden Sie streng
Richtlinie in JavaScript[14][15][16] und Perl Wendet eine stärkere Überprüfung an. - Das
deklarieren (strict_types = 1)
in Php[17] Auf der Basis pro Datei ermöglicht es nur eine Variable des genauen Typs der Typdeklaration akzeptiert oder aTypeerror
wird geworfen. - Das
Option Strict On
in Vb.net Ermöglicht dem Compiler, eine Konvertierung zwischen Objekten zu benötigen.
Zusätzliche Tools wie z. Fussel und IBM Rational Purify kann auch verwendet werden, um ein höheres Maß an Strenge zu erreichen.
Optionale Typsysteme
Es wurde vorgeschlagen, hauptsächlich von Gilad Bracha, dass die Wahl des Typsystems unabhängig von der Auswahl der Sprache getroffen wird; dass ein Typsystem ein Modul sein sollte, das sein kann verstopft nach Bedarf in eine Sprache. Er glaubt, dass dies vorteilhaft ist, weil das, was er obligatorische Typsysteme nennt, Sprachen weniger ausdrucksstarker und Code zerbrechlicher machen.[18] Die Anforderung, dass das Typsystem die Semantik der Sprache nicht beeinflusst, ist schwer zu erfüllen.
Optionales Tippen hängt mit, aber unterscheidet sich von, schrittweise Typisierung. Während beide Typisierungsdisziplinen verwendet werden können, um eine statische Analyse von Code durchzuführen (statische Typisierung) optionale Typsysteme erzwingen die Typensicherheit zur Laufzeit nicht (Dynamisches Typing). [18][19]
Polymorphismus und Typen
Der Begriff Polymorphismus Bezieht sich auf die Fähigkeit von Code (insbesondere von Funktionen oder Klassen), auf Werte mehrerer Typen oder auf die Fähigkeit verschiedener Instanzen derselben Datenstruktur zu reagieren, Elemente verschiedener Typen zu enthalten. Typsysteme, die Polymorphismus im Allgemeinen tun, um das Potenzial für die Wiederverwendung von Code zu verbessern: In einer Sprache mit Polymorphismus müssen Programmierer nur eine Datenstruktur wie eine Liste oder eine implementieren Assoziatives Array einmal, anstatt für jede Art von Element, mit der sie es verwenden möchten. Aus diesem Grund nennen Informationswissenschaftler manchmal die Verwendung bestimmter Formen des Polymorphismus generische Programmierung. Die theoretischen Grundlagen des Polymorphismus sind eng mit denen von verwandt Abstraktion, Modularität und (in einigen Fällen) Subtyping.
Spezialisierte Typsysteme
Es wurden viele Typsysteme erstellt, die für die Verwendung in bestimmten Umgebungen mit bestimmten Datenarten oder für außerhalb des Bandes spezialisiert sind Statische Programmanalyse. Häufig basieren diese auf Ideen von formal Typentheorie und sind nur im Rahmen von Prototypenforschungssystemen verfügbar.
Die folgende Tabelle gibt einen Überblick über typische theoretische Konzepte, die in speziellen Typsystemen verwendet werden. Die Namen M, n, o Bereich über Begriffe und die Namen Bereich über Typen. Die folgende Notation wird verwendet:
- bedeutet, dass hat Typ ;
- ist das Anwendung von an ;
- (bzw. ) beschreibt den Typ, der sich aus dem Ersetzen aller Vorkommen der Typvariablen ergibt α (bzw. Begriffsvariable x) in τ nach dem Typ σ (resp. Begriff N).
Geben Sie Begriff ein | Notation | Bedeutung |
---|---|---|
Funktion | Wenn und , dann . | |
Produkt | Wenn , dann ist ein Paar S.T. und . | |
Summe | Wenn , dann ist die erste Injektion S.T. , oder ist die zweite Injektion S.T. . | |
Überschneidung | Wenn , dann und . | |
Union | Wenn , dann oder . | |
Aufzeichnung | Wenn , dann M hat ein Mitglied . | |
Polymorph | Wenn , dann für jeden Typ σ. | |
Existenziell | Wenn , dann für irgendeine Art σ. | |
Rekursiv | Wenn , dann . | |
Abhängige Funktion[a] | Wenn und , dann . | |
Abhängiges Paar[b] | Wenn , dann ist ein Paar S.T. und . | |
Abhängige Kreuzung[20] | Wenn , dann und . | |
Familiäre Kreuzung[20] | Wenn , dann für jede Begriff . | |
Familienvereinigung[20] | Wenn , dann für einen Begriff . |
Abhängige Typen
Abhängige Typen basieren auf der Idee, Skalare oder Werte zu verwenden, um den Typ eines anderen Werts genauer zu beschreiben. Zum Beispiel, könnte die Art von a sein Matrix. Wir können dann die Schreibregeln wie die folgende Regel für die Matrixmultiplikation definieren:
wo k, m, n sind willkürliche positive Ganzzahlwerte. Eine Variante von Ml genannt Abhängig ml wurde basierend auf diesem Typsystem erstellt, aber weil die Typprüfung für herkömmliche abhängige Typen ist unentscheidbarNicht alle Programme, die sie verwenden, können ohne Grenzen vom Typ überprüft werden. Abhängige ML begrenzt die Art von Gleichheit, für die sie sich entscheiden kann Presburger -Arithmetik.
Andere Sprachen wie z. Epigramm Machen Sie den Wert aller Ausdrücke in der Sprache entschlossen, damit diese Typprüfung entscheidbar sein kann. Im Allgemeinen jedoch Der Nachweis der Dekidabilität ist unentscheidbarSo viele Programme erfordern handgeschriebene Anmerkungen, die möglicherweise nicht trivial sind. Da dies den Entwicklungsprozess beeinträchtigt, bieten viele Sprachimplementierungen einen einfachen Ausweg in Form einer Option, um diesen Zustand zu deaktivieren. Dies gilt jedoch auf Kosten, um den Typ-Prüfer in einem zu betreiben Endlosschleife Wenn Programme, die nicht tippen, nicht typern, und die Zusammenstellung fehlschlägt.
Lineare Typen
Lineare Typenbasierend auf der Theorie von lineare Logikund eng verwandt mit Einzigartigkeitstypen, sind Typen, die Werten mit der Eigenschaft zugeordnet sind, dass sie ein und nur einen Verweis auf sie zu jeder Zeit haben. Diese sind wertvoll, um große zu beschreiben unveränderliche Werte wie Dateien, Zeichenfolgen usw., weil jede Operation, die gleichzeitig ein lineares Objekt zerstört und ein ähnliches Objekt erstellt (wie z.str = str + "a"
') kann "unter der Motorhaube" in eine In-Place-Mutation optimiert werden. Normalerweise ist dies nicht möglich, da solche Mutationen Nebenwirkungen auf Teile des Programms verursachen können, die andere Verweise auf das Objekt halten und verletzen Referenztransparenz. Sie werden auch im Prototyp -Betriebssystem verwendet Singularität Für die Interprozesskommunikation stellt sich statisch sicher, dass Prozesse Objekte nicht im gemeinsamen Speicher teilen können, um die Rassenbedingungen zu verhindern. Das Sauber Sprache (a Haskell-ähnliche Sprache) verwendet dieses Typsystem, um viel Geschwindigkeit (im Vergleich zur Durchführung einer tiefen Kopie) zu gewinnen und gleichzeitig sicher zu bleiben.
Kreuzungstypen
Kreuzungstypen sind Typen, die Werte beschreiben, die zu gehören beide von zwei anderen gegebenen Typen mit überlappenden Wertsätzen. In den meisten Implementierungen von C verfügt der signierte Zeichen beispielsweise in einem Bereich von -128 bis 127 und der nicht signierte Zeichen hat einen Bereich von 0 bis 255 in Funktionen erwarten entweder Unterschriebene oder nicht signierte Zeichen, weil sie mit beiden Typen kompatibel sind.
Schnitttypen sind nützlich, um überlastete Funktionstypen zu beschreiben: beispielsweise wenn "int
→ int
"Ist die Art von Funktionen, die ein ganzzahliges Argument nutzen und eine Ganzzahl zurückgeben, und"float
→ float
"Ist die Art von Funktionen, die ein Float -Argument aufnehmen und einen Schwimmer zurückgeben, dann kann der Schnittpunkt dieser beiden Typen verwendet werden, um Funktionen zu beschreiben, die das eine oder andere erledigen, basierend auf der Art von Eingabe, die sie erhalten. Eine solche Funktion könnte sein übergeben in eine andere Funktion und erwartet eine "int
→ int
"Funktion sicher; es würde einfach nicht die" verwenden "float
→ float
"Funktionalität.
In einer unterklassigen Hierarchie ist der Schnittpunkt eines Typs und eines Vorfahren (wie der Elternteil) der am meisten abgeleitete Typ. Der Schnittpunkt der Geschwistertypen ist leer.
Die Forsythe -Sprache umfasst eine allgemeine Implementierung von Schnittartentypen. Eine eingeschränkte Form ist Verfeinerungstypen.
Gewerkschaftstypen
Gewerkschaftstypen sind Typen, die Werte beschreiben, die zu gehören entweder von zwei Arten. Zum Beispiel hat der signierte Zeichen in C einen Bereich von -128 bis 127, und das nicht signierte Zeichen hat einen Bereich von 0 bis 255 Teilweise verwendet werden, je nachdem, auf welches Gewerkschaftsmitglied zugegriffen wird. Jede Funktion, die mit diesem Gewerkschaftstyp handelt, müsste sich mit Ganzzahlen in diesem gesamten Bereich befassen. Im Allgemeinen sind die einzigen gültigen Operationen an einem Gewerkschaftstyp Operationen, die gültig sind beide Typen, die gewerkschaftlich gewerkschaftlich sind. Das "Gewerkschafts" -Konzept von C ähnelt Gewerkschaftstypen, ist jedoch nicht typesafe, da es Operationen ermöglicht, die gültig sind entweder Typ, anstatt beide. Gewerkschaftstypen sind wichtig in der Programmanalyse, bei der sie verwendet werden, um symbolische Werte darzustellen, deren genaue Natur (z. B. Wert oder Typ) nicht bekannt ist.
In einer subklassigen Hierarchie ist die Vereinigung eines Typs und eines Vorfahren (wie der Elternteil) der Vorfahrtyp. Die Vereinigung der Geschwistertypen ist ein Subtyp ihres gemeinsamen Vorfahren (dh alle Operationen, die auf ihren gemeinsamen Vorfahren zulässig sind, sind auf den Gewerkschaftstyp zulässig, haben jedoch möglicherweise auch andere gültige Operationen gemeinsam).
Existenzielle Typen
Existenziell Typen werden häufig in Verbindung mit verwendet Datensatztypen zu repräsentieren Module und Abstrakte Datentypen, aufgrund ihrer Fähigkeit, die Implementierung von der Schnittstelle zu trennen. Zum Beispiel beschreibt der Typ "t = ∃x {a: x; f: (x → int);}" eine Modulschnittstelle mit einem Datenelement mit dem Namen namens a of type X und eine Funktion namens namens f Das erfordert einen Parameter der gleich Typ X und gibt eine Ganzzahl zurück. Dies könnte auf unterschiedliche Weise implementiert werden; zum Beispiel:
- intt = {a: int; f: (int → int); }
- floatt = {a: float; f: (float → int); }
Diese Typen sind beide Subtypen des allgemeineren existentiellen Typs T und entsprechen konkreten Implementierungstypen, so T.F (T.A) "ist gut gespielt, unabhängig davon, was der abstrakte Typ X ist. Dies gibt Flexibilität für die Auswahl von Typen, die für eine bestimmte Implementierung geeignet sind, während Clients, die nur Werte des Schnittstellentyps - des existentiellen Typs - verwenden, aus diesen Auswahlmöglichkeiten isoliert werden.
Im Allgemeinen ist es für den Typecheck unmöglich zu schließen, welcher existentielle Typ ein bestimmtes Modul gehört. Im obigen Beispiel intt {a: int; f: (int → int); } könnte auch den Typ ∃x {a: x; f: (int → int); }. Die einfachste Lösung besteht darin, jedes Modul mit seinem beabsichtigten Typ zu kommentieren, z. B.:
- intt = {a: int; f: (int → int); } wie ∃x {a: x; f: (x → int); }
Obwohl abstrakte Datentypen und Module seit einiger Zeit in Programmiersprachen implementiert wurden, ist es erst 1988 das John C. Mitchell und Gordon Plotkin Die formale Theorie unter dem Slogan festgelegt: "Abstrakte [Daten] -Typen haben existenziellen Typen".[21] Die Theorie ist eine zweite Ordnung Typed Lambda Calculus ähnlich zu System f, aber mit existenziell anstelle einer universellen Quantifizierung.
Schrittweise Typisierung
Schrittweise Typisierung ist ein Typsystem, bei dem Variablen entweder bei einem Typ zugewiesen werden können Kompilierungszeit (was statisches Typing ist) oder bei Laufzeit (Dies ist eine dynamische Typisierung) und ermöglicht es Softwareentwicklern, jeweils in einer einzelnen Sprache das Paradigma des Typs auszuwählen.[22] Insbesondere die allmähliche Typierung verwendet einen speziellen Typ mit dem Namen dynamisch Um statisch unbekannte Typen darzustellen, und die allmähliche Typisierung ersetzt den Begriff der Typ-Gleichheit durch eine neue Beziehung genannt Konsistenz Das bezieht den dynamischen Typ auf jeden anderen Typ. Die Konsistenzbeziehung ist symmetrisch, aber nicht transitiv.[23]
Explizite oder implizite Deklaration und Schlussfolgerung
Viele statische Typsysteme, wie die von C und Java, erfordern Typdeklarationen: Der Programmierer muss jede Variable explizit mit einem bestimmten Typ assoziieren. Andere, wie Haskells, treten auf Geben Sie Inferenz ein: Der Compiler zieht Schlussfolgerungen zu den Arten von Variablen, basierend darauf, wie Programmierer diese Variablen verwenden. Zum Beispiel bei einer Funktion f(x, y)
Das fügt hinzu x
und y
Zusammen kann der Compiler das schließen x
und y
Muss Zahlen sein - siehe Hinzufügen ist nur für Zahlen definiert. Somit jeder Anruf zu f
An anderer Stelle im Programm, die einen nicht numerischen Typ (z. B. eine Zeichenfolge oder Liste) als Argument angibt, würde ein Fehler signalisieren.
Numerische und String -Konstanten und Ausdrücke im Code können und häufig einen Typ in einem bestimmten Kontext implizieren. Zum Beispiel ein Ausdruck 3.14
könnte eine Art von Art von bedeuten Schwimmpunkt, während [1, 2, 3]
könnte eine Liste von Ganzzahlen implizieren - typischerweise eine Array.
Typ -Inferenz ist im Allgemeinen möglich, wenn dies der Fall ist berechenbar im fraglichen Typsystem. Selbst wenn die Inferenz für ein bestimmtes Typsystem im Allgemeinen nicht berechnet werden kann, ist eine Inferenz häufig für eine große Teilmenge von realen Programmen möglich. Haskells Typsystem, eine Version von Hindley -Milner, ist eine Einschränkung von System Fω zu sogenannten Rang-1-polymorphen Typen, in welcher Typinferenz berechnet werden kann. Die meisten Haskell-Compiler erlauben ein beliebiges Polymorphismus als Erweiterung, dies macht jedoch die Typinferenz nicht berechnet. (Typ Checking ist entschlossenund Rang-1-Programme haben jedoch immer noch Typinferenz; Polymorphe Programme mit höherem Rang werden abgelehnt, es sei denn, es wird explizite Typanmerkungen angegeben.)
Entscheidungsprobleme
Ein Typsystem, das Typen in Typumgebungen mit den Begriffen zuweist Geben Sie Regeln ein ist natürlich mit dem verbunden Entscheidungsprobleme von Geben Sie die Überprüfung ein, Typabilität, und Typ Besiedlung.[24]
- Bei einer Typumgebung , ein Begriff und ein Typ , entscheiden Sie, ob der Begriff kann dem Typ zugewiesen werden in der Typumgebung.
- Mit einem Begriff Entscheiden Sie, ob es eine Typumgebung gibt und ein Typ so dass der Begriff kann dem Typ zugewiesen werden In der Typumgebung .
- Bei einer Typumgebung und ein Typ entscheiden Sie, ob es einen Begriff gibt dem kann der Typ zugewiesen werden in der Typumgebung.
Einheitliches Typsystem
Einige Sprachen mögen C# oder Scala haben ein einheitliches Typsystem.[25] Das bedeutet, dass alle C# Typen einschließlich primitiver Typen erben von einem einzelnen Stammobjekt. Jeder Typ C# Erben aus der Objektklasse. Einige Sprachen wie Java und Raku, haben Sie einen Wurzeltyp, aber auch primitive Typen, die keine Objekte sind.[26] Java bietet Wrapper-Objekttypen, die zusammen mit den primitiven Typen existieren, sodass Entwickler entweder die Wrapper-Objekttypen oder die einfacheren nicht-objekt-primitiven Typen verwenden können. Raku konvertiert automatisch primitive Typen in Objekte, wenn auf ihre Methoden zugegriffen werden.[27]
Kompatibilität: Äquivalenz und Subtyping
Ein Typ-Checker für eine staatlich-typische Sprache muss überprüfen, ob der Typ einer beliebten Ausdruck stimmt mit dem Typ überein, der durch den Kontext erwartet wird, in dem dieser Ausdruck erscheint. Zum Beispiel in einem Zuweisungsanweisung der Form x: = e
, die abgeleitete Art des Ausdrucks e
muss mit dem deklarierten oder abgeleiteten Typ der Variablen übereinstimmen x
. Dieser Begriff der Konsistenz, genannt Kompatibilität, ist spezifisch für jede Programmiersprache.
Wenn die Art von e
und die Art von x
sind die gleichen und die Zuordnung ist für diesen Typ zulässig, dann ist dies ein gültiger Ausdruck. In den einfachsten Typsystemen reduziert sich die Frage, ob zwei Typen kompatibel sind gleich (oder Äquivalent). Verschiedene Sprachen haben jedoch unterschiedliche Kriterien für die Bezeichnung von zwei Typausdrücken, um denselben Typ zu bezeichnen. Diese unterschiedlich Gleichungstheorien Die Typen variieren stark, zwei extreme Fälle sind Struktursysteme, in denen zwei Arten, die Werte mit derselben Struktur beschreiben, äquivalent sind und Nominative Typsysteme, in denen keine zwei syntaktisch unterschiedlichen Typausdrücke denselben Typ bezeichnen (d.h., Typen müssen den gleichen "Namen" haben, um gleich zu sein).
In Sprachen mit SubtypingDie Kompatibilitätsbeziehung ist komplexer. Insbesondere wenn, wenn B
ist ein Subtyp von A
, dann ein Wert des Typs B
kann in einem Kontext verwendet werden, in dem eine vom Typ A
wird erwartet (Kovariante), auch wenn das Gegenteil nicht wahr ist. Wie die Äquivalenz wird die Subtyp -Beziehung für jede Programmiersprache mit vielen Variationen unterschiedlich definiert. Das Vorhandensein von parametrischen oder ad hoc Polymorphismus In einer Sprache kann auch Auswirkungen auf die Typkompatibilität haben.
Siehe auch
- Vergleich der Typsysteme
- Kovarianz und Kontravarianz (Informatik)
- Polymorphismus in objektorientierter Programmierung
- Geben Sie Regeln ein
- Geben Sie Signatur ein
- Typentheorie
Anmerkungen
- ^ Das Burroughs Algol Computer Zeile bestimmte den Inhalt eines Speicherorts durch seine Flaggenbits. Flag -Bits geben den Inhalt eines Speicherorts an. Befehl, Datentyp und Funktionen werden zusätzlich zu seinem 48 -Bit -Inhalt durch einen 3 -Bit -Code angegeben. Nur das MCP (Master Control Program) konnte in die Flag -Code -Bits schreiben.
Verweise
- ^ Pierce 2002, p. 1: "Ein Typsystem ist eine syntaktische Methode, um das Fehlen bestimmter Programmverhalten zu beweisen, indem Phrasen nach den Arten von Werten klassifiziert werden, die sie berechnen."
- ^ Cardelli 2004, p. 1: "Der grundlegende Zweck eines Typsystems besteht darin, das Auftreten von Ausführungsfehlern während der Ausführung eines Programms zu verhindern."
- ^ Pierce 2002, p. 208.
- ^ "... jeder Ton, ein lichtbares Typsystem muss unvollständig sein" - d. Remy (2017). p. 29, Remy, Didier. "Typsysteme für Programmiersprachen" (PDF). Abgerufen 26. Mai 2013.
- ^ Pierce 2002.
- ^ Gaurav Miglani, Gaurav (2018). "Dynamische Methode Versand oder Laufzeitpolymorphismus in Java". Archiviert von das Original am 2020-12-07. Abgerufen 2021-03-28.
- ^ Wright, Andrew K. (1995). Praktische weiche Typisierung (PhD). Rice University. HDL:1911/16900.
- ^ "Dynamisch (C# Referenz)". MSDN -Bibliothek. Microsoft. Abgerufen 14. Januar 2014.
- ^ "Std :: Any - Rost". doc.rustlang.org. Abgerufen 2021-07-07.
- ^ Meijer, Erik; Drayton, Peter. "Statische Tippen, wo möglich, dynamische Tippen bei Bedarf: das Ende des Kalten Krieges zwischen den Programmiersprachen" (PDF). Microsoft Konzern.
- ^ Laucher, Amanda; Snively, Paul (2012). "Typen gegen Tests". Infoq.
- ^ XI, Hongwei (1998). Abhängige Typen in der praktischen Programmierung (PhD). Abteilung für Mathematische Wissenschaften, Carnegie Mellon University. Citeseerx 10.1.1.41.548.
XI, Hongwei; Pfenning, Frank (1999). "Abhängige Typen in der praktischen Programmierung". Verfahren des 26. ACM Sigplan-Sigact-Symposiums über Prinzipien der Programmiersprachen. ACM. S. 214–227. Citeseerx 10.1.1.69.2042. doi:10.1145/292540.292560. ISBN 1581130953. S2CID 245490. - ^ Visual Basic ist ein Beispiel für eine Sprache, die sowohl Typ-Sicherheit als auch Gedächtnissicher ist.
- ^ "4.2.2 Die strenge Variante von ECMascript". ECMAScript® 2020 Sprachspezifikation (11. Aufl.). ECMA. Juni 2020. ECMA-262.
- ^ "Strenge Modus - JavaScript". Mdn. Entwickler.mozilla.org. 2013-07-03. Abgerufen 2013-07-17.
- ^ "Strikter Modus (JavaScript)". Msdn. Microsoft. Abgerufen 2013-07-17.
- ^ "Strikte Schreiben". PHP -Handbuch: Sprachreferenz: Funktionen.
- ^ a b Bracha, G. "Steckbare Typen" (PDF).
- ^ "Sicher. Es heißt" schrittweise Tippen ", und ich würde es als trendy qualifizieren. ..." Gibt es eine Sprache, die sowohl eine statische als auch dynamische Tippen ermöglicht?. Paketüberfluss. 2012.
- ^ a b c Kopylov, Alexei (2003). "Abhängige Kreuzung: Eine neue Art der Definition von Datensätzen in der Typtheorie". 18. IEEE -Symposium über Logik in Informatik. LICs 2003. IEEE Computer Society. S. 86–95. Citeseerx 10.1.1.89.4223. doi:10.1109/lics.2003.1210048.
- ^ Mitchell, John C.; Plotkin, Gordon D. (Juli 1988). "Abstrakte Typen haben existenziellen Typ" (PDF). ACM trans. Programm. Lang. System. 10 (3): 470–502. doi:10.1145/44501.45065. S2CID 1222153.
- ^ Siek, Jeremy (24. März 2014). "Was ist allmähliches Tippen?".
- ^ Siek, Jeremy; Taha, Walid (September 2006). Schrittweise Typisierung für funktionale Sprachen (PDF). Schema und funktionelle Programmierung 2006. Universität von Chicago. S. 81–92.
- ^ Barendregt, Henk; Dekkers, Wil; Statman, Richard (20. Juni 2013). Lambda -Kalkül mit Typen. Cambridge University Press. p. 66. ISBN 978-0-521-76614-2.
- ^ "8.2.4 Typ Systemeinheitung". C# Sprachspezifikation (5. Aufl.). ECMA. Dezember 2017. ECMA-334.
- ^ "Einheimische Typen". Perl 6 Dokumentation.
- ^ "Numerics, § Auto-Boxing". Perl 6 Dokumentation.
Weitere Lektüre
- Cardelli, Luca; Wegner, Peter (Dezember 1985). "Über das Verständnis von Typen, Datenabstraktion und Polymorphismus" (PDF). ACM Computing -Umfragen. 17 (4): 471–523. Citeseerx 10.1.1.117.695. doi:10.1145/6041.6042. S2CID 2921816.
- Pierce, Benjamin C. (2002). Typen und Programmiersprachen. MIT Press. ISBN 978-0-262-16209-8.
- Cardelli, Luca (2004). "Typsysteme" (PDF). In Allen B. Tucker (Hrsg.). CRC -Handbuch für Informatik und Ingenieurwesen (2. Aufl.). CRC Press. ISBN 978-1584883609.
- Tratt, Laurence (Juli 2009). "5. Dynamisch getippte Sprachen". Fortschritte in Computern. Vol. 77. Elsevier. S. 149–184. doi:10.1016/s0065-2458 (09) 01205-4. ISBN 978-0-12-374812-6.
Externe Links
- Medien im Zusammenhang mit Typsystemen bei Wikimedia Commons
- Smith, Chris (2011). "Was zu wissen, bevor Sie über Typsysteme diskutieren".