Zunächst möchte ich sagen, dass Java die einzige Sprache ist, die ich jemals verwendet habe. Entschuldigen Sie bitte meine Unkenntnis zu diesem Thema.
Mit dynamisch getippten Sprachen können Sie in jede Variable einen beliebigen Wert eingeben. So könnten Sie zum Beispiel die folgende Funktion schreiben (psuedocode):
void makeItBark(dog){
dog.bark();
}
Und Sie können darin jeden Wert weitergeben. Solange der Wert eine bark()
Methode hat, wird der Code ausgeführt. Andernfalls wird eine Laufzeitausnahme oder ähnliches ausgelöst. (Bitte korrigieren Sie mich, wenn ich mich irre).
Dies gibt Ihnen anscheinend Flexibilität.
Ich habe jedoch etwas über dynamische Sprachen gelesen, und was die Leute sagen, ist, dass Sie beim Entwerfen oder Schreiben von Code in einer dynamischen Sprache über Typen nachdenken und diese berücksichtigen, genauso wie Sie es in einer statisch getippten Sprache tun würden.
Wenn makeItBark()
Sie beispielsweise die Funktion schreiben , möchten Sie, dass sie nur "Dinge akzeptiert, die bellen können", und Sie müssen weiterhin sicherstellen, dass Sie nur diese Art von Dingen übergeben. Der einzige Unterschied ist, dass der Compiler Ihnen jetzt nicht sagt, wann Sie einen Fehler gemacht haben.
Sicher, es gibt einen Vorteil dieses Ansatzes: Um in statischen Sprachen zu erreichen, dass diese Funktion alles akzeptiert, was bellen kann, müssen Sie eine explizite Barker
Schnittstelle implementieren . Dies scheint jedoch ein kleiner Vorteil zu sein.
Vermisse ich etwas? Was verdiene ich eigentlich mit einer dynamisch getippten Sprache?
quelle
makeItBark(collections.namedtuple("Dog", "bark")(lambda x: "woof woof"))
. Dieses Argument ist nicht einmal eine Klasse , es ist ein anonymes Tupel mit dem Namen. Duck Typing ("wenn es wie ein ... quakt") ermöglicht es Ihnen, Ad-hoc-Schnittstellen mit im Wesentlichen null Einschränkungen und ohne syntaktischen Aufwand zu erstellen. Sie können dies in einer Sprache wie Java tun, aber Sie haben am Ende viel chaotisches Nachdenken. Wenn für eine Funktion in Java eine ArrayList erforderlich ist und Sie ihr einen anderen Auflistungstyp zuweisen möchten, sind Sie SOL. In Python kann das nicht einmal hochkommen.bark()
Methode funktioniert , wobei der Compiler sich beschwert, wenn Sie etwas Falsches übergeben, ohne tatsächlich eine Schnittstelle deklarieren zu müssen, die bark () enthält.getMember
Funktion abgerufen werden, kommt es zu einermakeItBark
Explosion, weil Siedog.bark
anstelle von aufgerufen habendog.getMember("bark")
. Der Code funktioniert nur, wenn alle implizit der Verwendung des nativen Objekttyps von Python zustimmen.Just because I wrote makeItBark with my own types in mind doesn't mean you can't use yours, wheras in a static language it probably /does/ mean that.
Wie in meiner Antwort ausgeführt, ist dies im Allgemeinen nicht der Fall . Dies ist bei Java und C # der Fall, aber diese Sprachen weisen verkrüppelte Typ- und Modulsysteme auf, sodass sie nicht repräsentativ für die Möglichkeiten der statischen Typisierung sind. Ich kann ein perfektes GenerikummakeItBark
in mehreren statisch typisierten Sprachen schreiben , sogar in nicht funktionalen Sprachen wie C ++ oder D.Antworten:
Dynamisch getippte Sprachen werden einheitlich getippt
Beim Vergleich von Typsystemen bietet das dynamische Schreiben keinen Vorteil. Dynamische Typisierung ist ein Sonderfall der statischen Typisierung - es ist eine Sprache mit statischer Typisierung, bei der jede Variable denselben Typ hat. Sie können das Gleiche in Java erreichen (Minuspräzision), indem Sie dafür sorgen, dass jede Variable vom Typ
Object
ist und dass "Objekt" -Werte vom Typ sindMap<String, Object>
:Selbst ohne Reflektion können Sie den gleichen Effekt in nahezu jeder statisch typisierten Sprache erzielen, abgesehen von der syntaktischen Bequemlichkeit. Sie erhalten keine zusätzliche Ausdruckskraft. im Gegenteil, Sie haben weniger Aussagekraft , weil in einer dynamisch typisierte Sprache, werden Sie verweigern die Möglichkeit , Variablen auf bestimmte Arten zu beschränken.
Eine Entenrinde in einer statisch typisierten Sprache bellen lassen
Darüber hinaus können Sie mit einer guten statischen Sprache Code schreiben, der mit jedem Typ mit einer
bark
Operation funktioniert. In Haskell ist dies eine Typklasse:Dies drückt die Einschränkung aus, dass für einen Typ
a
, der als Barkable betrachtet werden soll, einebark
Funktion vorhanden sein muss , die einen Wert dieses Typs annimmt und nichts zurückgibt.Sie können dann generische Funktionen in Bezug auf die
Barkable
Einschränkung schreiben :Dies bedeutet, dass
makeItBark
es für jeden Typ geeignet istBarkable
, der die Anforderungen erfüllt. Dies maginterface
Java oder C # ähneln, hat aber einen großen Vorteil: Typen müssen nicht im Voraus angeben , welchen Typklassen sie entsprechen. Ich kann diese Art sagenDuck
istBarkable
jederzeit, auch wennDuck
ein Dritte Typ ich nicht schreiben. Tatsächlich spielt es keine Rolle, dass der Schreiber vonDuck
keinebark
Funktion geschrieben hat - ich kann sie nachträglich bereitstellen, wenn ich der Sprache sage, die FolgendesDuck
erfülltBarkable
:Dies besagt, dass
Duck
s bellen können, und ihre Barkenfunktion wird implementiert, indem die Ente gestanzt wird, bevor sie quakt. Wenn das nicht im Weg ist, können wirmakeItBark
Enten suchen.Standard ML
undOCaml
sind noch flexibler, da Sie dieselbe Typenklasse auf mehr als eine Weise erfüllen können. In diesen Sprachen kann ich sagen, dass ganze Zahlen mit der herkömmlichen Reihenfolge geordnet werden können und sich dann umdrehen und sagen, dass sie auch durch Teilbarkeit geordnet werden können (z. B.10 > 5
weil 10 durch 5 teilbar ist). In Haskell können Sie eine Typklasse nur einmal instanziieren. (Auf diese Weise weiß Haskell automatisch, dass es in Ordnung ist,bark
eine Ente anzurufen . In SML oder OCaml müssen Sie genau angeben, welchebark
Funktion Sie möchten, da es möglicherweise mehr als eine geben kann.)Prägnanz
Natürlich gibt es syntaktische Unterschiede. Der von Ihnen vorgestellte Python-Code ist weitaus prägnanter als das von mir geschriebene Java-Äquivalent. In der Praxis ist diese Prägnanz ein wesentlicher Bestandteil der Faszination dynamisch typisierter Sprachen. Aber Typinferenz ermöglicht es Ihnen , Code zu schreiben, in nur so kurz ist statisch typisierten Sprachen, indem Sie entlasten zu müssen explizit die Typen schreiben jede Variable. Eine statisch typisierte Sprache kann auch native Unterstützung für dynamisches Schreiben bieten und die Ausführlichkeit aller Casting- und Kartenmanipulationen (z. B. C #
dynamic
) beseitigen .Richtige, aber falsch geschriebene Programme
Um fair zu sein, schließt statische Typisierung notwendigerweise einige technisch korrekte Programme aus, obwohl die Typprüfung dies nicht überprüfen kann. Beispielsweise:
Die meisten statisch typisierten Sprachen würden diese
if
Anweisung ablehnen , obwohl die else-Verzweigung niemals auftreten wird. In der Praxis scheint niemand diese Art von Code zu verwenden - alles, was für die Typprüfung zu clever ist, wird wahrscheinlich dazu führen, dass zukünftige Betreuer Ihres Codes Sie und Ihre nächsten Verwandten verfluchen. Beispiel: Jemand hat erfolgreich 4 Open-Source-Python-Projekte in Haskell übersetzt, was bedeutet, dass er nichts getan hat, was eine gute statisch typisierte Sprache nicht kompilieren konnte. Außerdem stellte der Compiler einige typbezogene Fehler fest, die bei den Komponententests nicht festgestellt wurden.Das stärkste Argument, das ich für dynamisches Tippen gesehen habe, sind Lisps Makros, da Sie damit die Syntax der Sprache beliebig erweitern können. Allerdings typisierten Racket ist eine statisch typisierte Dialekt von Lisp , die Makros hat, so dass es statische Typisierung scheint und Makros schließen sich nicht aus, wenn auch vielleicht härter gleichzeitig zu implementieren.
Äpfel und Orangen
Vergessen Sie nicht, dass die Unterschiede in den Sprachen größer sind als nur das Typensystem. Vor Java 8 war es praktisch unmöglich , irgendeine Art von funktionaler Programmierung in Java durchzuführen. Ein einfaches Lambda würde 4 Zeilen Boilerplate-Code für anonyme Klassen erfordern. Java unterstützt auch keine Sammlungsliterale (z
[1, 2, 3]
. B. ). Es kann auch Unterschiede in der Qualität und Verfügbarkeit von Tools (IDEs, Debuggern), Bibliotheken und Community-Support geben. Wenn jemand behauptet, in Python oder Ruby produktiver zu sein als in Java, muss diese Ungleichheit der Funktionen berücksichtigt werden. Es gibt einen Unterschied zwischen dem Vergleichen von Sprachen mit allen enthaltenen Batterien , Sprachkernen und Typensystemen .quelle
Dies ist ein schwieriges und recht subjektives Thema. (Und Ihre Frage wird möglicherweise als meinungsbasiert geschlossen, aber das bedeutet nicht, dass es eine schlechte Frage ist - im Gegenteil, auch wenn das Nachdenken über solche metasprachlichen Fragen ein gutes Zeichen ist -, ist es einfach nicht gut für das Q & A-Format geeignet dieses Forums.)
Hier ist meine Ansicht dazu: Der Sinn von Hochsprachen besteht darin, die Möglichkeiten eines Programmierers mit dem Computer einzuschränken . Dies ist für viele Menschen überraschend, da sie der Ansicht sind, dass es das Ziel ist, den Benutzern mehr Macht zu geben und mehr zu erreichen . Da jedoch alles, was Sie in Prolog, C ++ oder List schreiben, irgendwann als Maschinencode ausgeführt wird, ist es unmöglich, dem Programmierer mehr Leistung zu geben, als die Assemblersprache bereits bietet.
Der Sinn einer Hochsprache ist es , dem Programmierer zu helfen, den von ihm selbst erstellten Code besser zu verstehen und ihn effizienter zu machen, wenn es darum geht, dasselbe zu tun. Ein Unterprogrammname ist leichter zu merken als eine hexadezimale Adresse. Ein automatischer Argumentenzähler ist einfacher zu verwenden als eine Aufrufsequenz. Hier müssen Sie die Anzahl der Argumente ohne Hilfe exakt selbst bestimmen. Ein Typensystem geht weiter und schränkt das ein Art der Argumente ein, die Sie an einer bestimmten Stelle angeben können.
Hier unterscheidet sich die Wahrnehmung der Menschen. Einige Leute (ich gehöre dazu) sind der Meinung, dass es nützlich ist, dies im Code zu deklarieren und automatisch daran erinnert zu werden, wenn Ihre Kennwortprüfroutine ohnehin genau zwei Argumente und immer eine Zeichenfolge gefolgt von einer numerischen ID erwartet Sie vergessen später, diese Regel zu befolgen. Das Auslagern einer solchen kleinen Buchhaltung an den Compiler befreit Sie von übergeordneten Problemen und erleichtert das Entwerfen und Entwickeln Ihres Systems. Daher sind Typsysteme ein Nettogewinn: Sie lassen den Computer tun, was er kann, und Menschen tun, was sie können.
Andere sehen das ganz anders. Sie mögen es nicht, von einem Compiler gesagt zu werden, was zu tun ist. Ihnen missfällt der zusätzliche Aufwand, sich für die Typdeklaration zu entscheiden und diese zu tippen. Sie bevorzugen einen explorativen Programmierstil, bei dem Sie tatsächlichen Geschäftscode schreiben, ohne einen Plan zu haben, der Ihnen genau sagt, welche Typen und Argumente wo verwendet werden sollen. Und für die Art der Programmierung, die sie verwenden, mag dies durchaus zutreffen.
Ich vereinfache das hier natürlich schrecklich. Die Typprüfung ist nicht streng an explizite Typdeklarationen gebunden. Es gibt auch Typinferenz. Das Programmieren mit Routinen, die tatsächlich Argumente unterschiedlicher Art verwenden, ermöglicht ganz andere und sehr mächtige Dinge, die sonst unmöglich wären. Es ist nur so, dass viele Leute nicht aufmerksam und konsistent genug sind, um diesen Spielraum erfolgreich zu nutzen.
Letztendlich zeigt die Tatsache, dass so unterschiedliche Sprachen sehr beliebt sind und keine Anzeichen eines Absterbens zeigen, dass die Leute sehr unterschiedlich programmieren. Ich denke, dass es bei den Features von Programmiersprachen hauptsächlich um menschliche Faktoren geht - was den menschlichen Entscheidungsprozess besser unterstützt - und solange Menschen sehr unterschiedlich arbeiten, wird der Markt gleichzeitig sehr unterschiedliche Lösungen anbieten.
quelle
Mit dynamischen Sprachen geschriebener Code ist nicht an ein statisches Typsystem gekoppelt. Daher ist dieses Fehlen einer Kopplung ein Vorteil im Vergleich zu schlechten / unzureichenden statischen Systemen (obwohl es im Vergleich zu einem großen statischen System eine Wäsche oder ein Nachteil sein kann).
Darüber hinaus muss für eine dynamische Sprache ein statisches Typsystem nicht entworfen, implementiert, getestet und gewartet werden. Dies könnte die Implementierung im Vergleich zu einer Sprache mit einem statischen Typsystem vereinfachen.
quelle