Wie wirkt sich ein statisches Typensystem auf das Design einer prototypbasierten Sprache aus?

15

Der Wikipedia-Artikel über prototypbasierte Sprachen enthält den folgenden Absatz:

Fast alle prototypbasierten Systeme basieren auf interpretierten und dynamisch typisierten Sprachen. Systeme, die auf statisch typisierten Sprachen basieren, sind jedoch technisch machbar.

Inwiefern unterwirft ein statisches Typensystem Einschränkungen oder führt zu Komplexität in der prototypbasierten Sprache, und warum gibt es dynamischere Prototypensprachen?

Joe
quelle
2
+1 und fav'd: Ich habe eine ganze Weile darüber nachgedacht und keine außerordentlich schweren Probleme mit einem strukturellen Typensystem festgestellt . Tatsächlich stört mich das so sehr, dass ich versuchen möchte, eine statisch typisierte prototypbasierte Sprache zu erstellen, um zu sehen, welche Probleme es gibt ...
Ich fange gerade aus dem gleichen Grund damit an :)
Joe

Antworten:

6

Die Grenze zwischen einem Grundtyp und einem Objekt ist verschwommen und oft künstlich eingeführt. In C ist eine Struktur beispielsweise nur eine Reihe von Datensätzen, nur ein abgeleiteter Nicht-Objekttyp. In C ++ ist eine Struktur eine Klasse mit allen öffentlichen Feldern, ein Objekt. Trotzdem ist C ++ fast vollständig abwärtskompatibel mit C ... der Rand ist hier wirklich weich.

Für die prototypbasierte Programmierung müssen Objekte zur Laufzeit veränderbar sein. Sie MÜSSEN weich geschrieben sein, da sich jede Änderung zur Laufzeit ändert, eine Klasse einer Art in eine andere - ihr Typ ändert sich.

Sie können jedoch grundlegende und abgeleitete Nicht-Objekttypen als statisch beibehalten. Dies führt jedoch zu einer merkwürdigen Ungleichheit, Objekte sind weich, Nicht-Objekte sind statisch, und es muss eine harte Grenze zwischen den beiden festgelegt werden. Solltest du in der Lage sein, eine Struktur zu verändern? Ein Faden? Sollte Number eine Klasse oder ein Fundamentaltyp oder eine Menge von Fundamentaltypen sein, int / float / bignum / etc?

Es ist nur natürlicher und einfacher, diese Uniform zu erlernen, zu verwenden und zu schreiben. Alle Typen sind zur Laufzeit veränderbar oder es sind keine Typen veränderbar. Wenn Sie nur einen Typ (Objekt) für veränderlich erklären, bekommen Sie Kopfschmerzen und Probleme beider Welten.

Statisch eingegeben ist:

  • einfacher zu implementieren
  • schneller / effizienter
  • sicherer
  • Einfachere Wartung / Dokumentation großer Systeme durch Abstraktion.

Dynamisch eingegeben ist:

  • schneller zu schreiben,
  • prägnanter
  • Sprache leichter zu lernen
  • mehr Vergebung für Designfehler.

Indem Sie die zwei mischen, opfern Sie viel.

  • Die Implementierung wird schwieriger als bei den beiden vorherigen.
  • Geschwindigkeit hängt davon ab, ob Sie die weichen Typen verwenden oder nicht ... Wenn ja, ist es niedrig, wenn nicht, warum überhaupt die Sprache auswählen?
  • Typensicherheit ist für alle Objekttypen aus dem Fenster.
  • zu verfolgen, wie sich ein Typ in einen anderen verwandelt, ist eine ziemlich schwierige Aufgabe. Dokumentieren - sehr schwer.
  • Sie müssen die gesamte Buchhaltung mit grundlegenden Typen durchführen, was die Prägnanz und die Schreibgeschwindigkeit zunichte macht
  • Die Sprachkomplexität ist höher (schwieriger zu erlernen) als bei den "spezifischen",
  • "Verzeihen" eines dynamisch getippten Attributtyps wird durch die Tendenz zu einigen sehr kniffligen Fehlern bei der Nichtübereinstimmung von Attributtypen ersetzt.
SF.
quelle
1
Denken Sie daran, ein Beispiel anzugeben, warum Objekte "veränderbar" sein müssen (ich nehme an, Sie meinen das Hinzufügen und Entfernen von Attributen, ohne diese zu ändern, da dies normalerweise nichts mit dem Tippen zu tun hat).
@delnan: Nicht wirklich, bei der prototypbasierten Programmierung können Sie die Eingeweide eines Objekts nach Belieben in einer Live-Instanz nach Belieben durchsuchen, entfernen, hinzufügen, ersetzen, abdecken und Methoden und Attribute. Das ist der springende Punkt und ein sehr praktischer, flexibler Ersatz für das Ändern von Objekten durch starre Regeln der klassischen Vererbung. Wenn eine Sprache eine Klasse als Typ verwendet, können Sie ihre Struktur nicht direkt ändern, wenn der Typ nicht weich ist.
SF.
1
Ich glaube nicht. Nach der gleichen Logik könnte man argumentieren, dass klassenbasierte Programmierung die gleichen Freiheiten benötigt, wie sie dynamische klassenbasierte Sprachen erlauben. Nein, statische Prototypen mit Strukturtypsystemen würden Objekte mit einer Liste ihrer Mitglieder und rekursiv mit Anmerkungen versehen und statisch überprüfen, ob diese Mitglieder vorhanden sind (und den richtigen Typ haben), indem verlangt wird, dass alle Mitglieder bei der Objekterstellung angegeben werden oder in vorhanden sind der Prototyp und einfach keine Möglichkeit zum Entfernen von Mitgliedern. Das Ergebnis sieht für mich immer noch ziemlich prototypisch aus und garantiert, dass jedes Mitglied jederzeit anwesend ist.
@delnan: Du hast gerade die klassische Vererbung durch Komposition beschrieben. Ja, es sieht ziemlich prototypisch aus und ist eine (sehr ausgefeilte) Möglichkeit, prototypbasierte Programmierung in einer klassischen Vererbungsmodellsprache durchzuführen. Nur 90% des Spaßes entfallen, und die größten Vorteile werden zunichte gemacht (und gleichzeitig die größten Gefahren beseitigt). Ja, in der alten Fußschieß-Analogie hilft Ihnen pb.p mit vollem Funktionsumfang, beide Beine mit einem Teelöffel abzuschießen. Wenn Sie diese Art von Macht nicht mögen, sollten Sie sich besser an die klassische Vererbung halten.
SF.
1
Sie verwechseln "dynamisch" mit "Prototypen". Diese Freiheiten, die sich nicht gut mit statischen Typsystemen kombinieren lassen, sind keine Merkmale von Prototypen, sondern Merkmale von Dynamik. Das Hinzufügen von statischer Typisierung verhindert sie natürlich, aber sie sind kein Teil von Prototypen (das ist IMGO, das hauptsächlich keine Klassen für das Klonen von Objekten hat, die als Eltern fungieren sollen). Diese Dynamik ist orthogonal zu Prototypen. Alle gängigen Prototypensprachen enthalten sie, sie sind jedoch unabhängig von den zuvor genannten Prototypen. Betrachten Sie diesen Ausschnitt in einer fiktiven Sprache: pastebin.com/9pLuAu9F . Wie ist es nicht Prototypen?
3

Die Schwierigkeit ist ziemlich einfach zu erkennen: Wenn Sie die Ansicht von Objekten als Wörterbücher von Methoden oder als Dinge, die auf Nachrichten reagieren, betrachten, beachten Sie Folgendes in Bezug auf häufig verwendete statisch typisierte OO-Sprachen:

  • Alle Wörterbuchschlüssel / -nachrichten werden in der Regel im Voraus mit statisch deklarierten Bezeichnern deklariert.

  • Bestimmte Nachrichtensätze werden im Voraus deklariert, und diesen Sätzen werden Objekte zugeordnet, um zu bestimmen, auf welche Nachrichten sie antworten.

  • Einschlussbeziehungen einer Gruppe von Nachrichten, die eine Teilmenge einer anderen Gruppe sind, werden statisch und explizit deklariert. nicht deklariert, aber logische Teilmengen sind nicht gültig.

  • Bei der Typprüfung wird versucht, sicherzustellen, dass alle Nachrichten nur an Objekte gesendet werden, die darauf antworten.

Jeder dieser Punkte steht in gewissem Maße in Konflikt mit einem prototypbasierten System:

  • Die Nachrichtennamen könnten im Voraus in Form von "Atomen" oder internen Zeichenfolgen oder so weiter deklariert werden, aber sonst nichts. Die Plastizität von Objekten macht es schwierig, Methoden Typen zuzuweisen.

  • Es ist wohl das wesentliche Merkmal eines prototypbasierten Systems, dass Nachrichtensätze durch die Antwort eines Objekts definiert werden und nicht umgekehrt. Es wäre sinnvoll, Aliase zur Kompilierungszeit bestimmten Kombinationen zuzuweisen, aber zur Laufzeit ermittelte Nachrichtensätze müssen möglich sein.

  • Die tatsächlichen Auswirkungen der beiden oben genannten Treffer sind auf Einbeziehungsbeziehungen zurückzuführen, bei denen explizite Deklarationen völlig unbrauchbar sind. Vererbung im statischen, nominalen Subtypisierungssinn ist einem prototypbasierten System entgegengesetzt.

Das bringt uns zu dem letzten Punkt, den wir nicht wirklich ändern möchten. Wir möchten weiterhin sicherstellen, dass Nachrichten nur an Objekte gesendet werden, die darauf antworten. Jedoch:

  • Wir können nicht statisch wissen, welche Nachrichten zusammen gruppiert werden können.
  • Wir können nicht wissen, welche Gruppierungen Teilmengen anderer sind.
  • Wir können nicht wissen, welche Gruppierungen möglich sind.
  • Wir können nicht einmal spezifizieren, welche Art von Argumenten zusammen mit einer einzelnen Nachricht gesendet werden.
  • Grundsätzlich haben wir festgestellt, dass wir im allgemeinen Fall nicht viel von allem spezifizieren können.

Wie kann das nun umgangen werden? Begrenzen Sie entweder die vollständige Allgemeinheit (was unangenehm ist und schnell alle Vorteile der Verwendung eines prototypbasierten Systems zunichte macht) oder machen Sie das Typsystem viel flüssiger und drücken Sie Einschränkungen aus, anstatt exakte Typen .

Das auf Bedingungen basierende Typsystem führt schnell zu dem Begriff der strukturellen Untertypisierung , die in einem sehr losen Sinne als das statische Äquivalent der "Ententypisierung" angesehen werden kann. Die größten Hindernisse dabei sind, dass solche Systeme bei der Typüberprüfung viel komplizierter und weniger bekannt sind (was bedeutet, dass nur wenig Vorarbeit geleistet werden muss).

Zusammenfassend lässt sich sagen: Es ist möglich, dass es nur schwieriger ist als ein nominales statisches System oder ein dynamisches System, das auf Laufzeit-Metadaten basiert, und daher stören sich nur wenige Menschen.

CA McCann
quelle
1

Ich glaube, ein Weg, eine statisch typisierte, prototypbasierte Sprache zu erreichen, besteht darin, die Sprache auf Vorlagen und Konzepte zu stützen.

Konzepte waren einst ein geplantes Feature für C ++ 0x. Generischer Code in C ++ - Vorlagen ist de facto bereits "statisch ententypisiert". Die Idee von Concepts ist, in der Lage zu sein, einige Dinge über erforderliche Elemente und Merkmale von Typen zu sagen, ohne ein Klassenvererbungsmodell zu erfordern oder zu implizieren, das dieser Beziehung zugrunde liegt (weil es mit vorhandenem Vorlagencode funktionieren musste, der bereits "statisch getippt" war. ).

In einer Sprache, die von Grund auf auf Vorlagen und Konzepten basiert, wären es die Konzepte, die auf Prototypen basieren, und Vorlagen würden Sie davon befreien, sich um Klassenmodelle zu kümmern, die zur Implementierung der Wertetypen verwendet werden können oder nicht.

Abgesehen von Tricks bei der Verwendung von Staged-Compilation, damit die Sprache ihre eigene Metasprache sein kann, wären diese prototypischen Ableitungen von Concepts nach ihrer Erstellung notwendigerweise unveränderlich. Der Einwand, dass dies kein Prototyp ist, ist jedoch ein roter Hering. Es wäre einfach eine funktionale Sprache. Zumindest wurde versucht, eine dynamische Prototyp-Basissprache zu entwickeln, die auch funktionsfähig ist .

Dennis Ferron
quelle