Die dynamisch getippten Sprachen, die ich kenne, lassen die Entwickler niemals die Variablentypen spezifizieren oder haben zumindest eine sehr eingeschränkte Unterstützung dafür.
JavaScript bietet beispielsweise keinen Mechanismus zum Erzwingen von Variablentypen, wenn dies zweckmäßig ist. PHP können Sie einige Arten von Methodenargumenten angeben, aber es gibt keine Möglichkeit , einheimische Arten zu verwenden ( int
, string
usw.) für die Argumente, und es gibt keine Möglichkeit , Typen für irgendetwas zu erzwingen andere als Argumente.
Gleichzeitig wäre es zweckmäßig, in einigen Fällen den Typ einer Variablen in einer dynamisch typisierten Sprache anzugeben, anstatt die Typprüfung manuell durchzuführen.
Warum gibt es eine solche Einschränkung? Ist es aus technischen / Performance-Gründen (ich nehme an, es ist im Fall von JavaScript) oder nur aus politischen Gründen (was, glaube ich, der Fall von PHP ist)? Ist dies ein Fall für andere dynamisch typisierte Sprachen, mit denen ich nicht vertraut bin?
Bearbeiten: Nach den Antworten und Kommentaren hier ein Beispiel zur Verdeutlichung: Nehmen wir an, wir haben die folgende Methode in normalem PHP:
public function CreateProduct($name, $description, $price, $quantity)
{
// Check the arguments.
if (!is_string($name)) throw new Exception('The name argument is expected to be a string.');
if (!is_string($description)) throw new Exception('The description argument is expected to be a string.');
if (!is_float($price) || is_double($price)) throw new Exception('The price argument is expected to be a float or a double.');
if (!is_int($quantity)) throw new Exception('The quantity argument is expected to be an integer.');
if (!$name) throw new Exception('The name argument cannot be an empty string.');
if ($price <= 0) throw new Exception('The price argument cannot be less or equal to zero.');
if ($price < 0) throw new Exception('The price argument cannot be less than zero.');
// We can finally begin to write the actual code.
// TODO: Implement the method here.
}
Mit einigem Aufwand kann dies umgeschrieben werden als (siehe auch Programmierung durch Verträge in PHP ):
public function CreateProduct($name, $description, $price, $quantity)
{
Component::CheckArguments(__FILE__, __LINE__, array(
'name' => array('value' => $name, 'type' => VTYPE_STRING),
'description' => array('value' => $description, 'type' => VTYPE_STRING),
'price' => array('value' => $price, 'type' => VTYPE_FLOAT_OR_DOUBLE),
'quantity' => array('value' => $quantity, 'type' => VTYPE_INT)
));
if (!$name) throw new Exception('The name argument cannot be an empty string.');
if ($price <= 0) throw new Exception('The price argument cannot be less or equal to zero.');
if ($price < 0) throw new Exception('The price argument cannot be less than zero.');
// We can finally begin to write the actual code.
// TODO: Implement the method here.
}
Die gleiche Methode würde jedoch wie folgt geschrieben, wenn PHP optional native Typen für Argumente akzeptieren würde:
public function CreateProduct(string $name, string $description, double $price, int $quantity)
{
// Check the arguments.
if (!$name) throw new Exception('The name argument cannot be an empty string.');
if ($price <= 0) throw new Exception('The price argument cannot be less or equal to zero.');
if ($price < 0) throw new Exception('The price argument cannot be less than zero.');
// We can finally begin to write the actual code.
// TODO: Implement the method here.
}
Welches ist kürzer zu schreiben? Welches ist leichter zu lesen?
quelle
Antworten:
Der Sinn der statischen Typisierung ist die Fähigkeit , statisch zu beweisen, dass Ihr Programm in Bezug auf Typen korrekt ist (Hinweis: Nicht in allen Sinnen vollständig korrekt). Wenn Sie durchgehend über ein statisches Typsystem verfügen, können Sie die meiste Zeit Tippfehler erkennen.
Wenn Sie nur teilweise Typinformationen haben, können Sie nur die kleinen Teile eines Aufrufdiagramms überprüfen, in denen die Typinformationen zufällig vollständig sind. Sie haben jedoch viel Zeit und Mühe aufgewendet, um Typinformationen für unvollständige Teile anzugeben, die Ihnen nicht weiterhelfen können, aber ein falsches Sicherheitsgefühl vermitteln können.
Um Typinformationen auszudrücken, benötigen Sie einen Teil der Sprache, der nicht allzu einfach sein kann. Bald werden Sie feststellen, dass Informationen wie
int
nicht genug sind; Sie möchten so etwas wieList<Pair<Int, String>>
dann parametrische Typen usw. Es kann verwirrend genug sein, auch im eher einfachen Fall von Java.Dann müssen Sie diese Informationen während der Übersetzungs- und Ausführungsphase verarbeiten, da es dumm ist, nur nach statischen Fehlern zu suchen. Der Benutzer wird erwarten, dass die Typeinschränkungen immer gelten, wenn sie überhaupt angegeben werden. Dynamische Sprachen sind nicht zu schnell, und solche Überprüfungen verlangsamen die Leistung noch mehr. Eine statische Sprache kann ernsthafte Anstrengungen unternehmen, um Typen zu überprüfen, da dies nur einmal durchgeführt wird. eine dynamische Sprache kann nicht.
Stellen Sie sich nun vor, Sie fügen all dies hinzu und warten es, damit Benutzer diese Funktionen manchmal optional verwenden und nur einen kleinen Bruchteil der Tippfehler erkennen. Ich denke nicht, dass es die Mühe wert ist.
Der springende Punkt dynamischer Sprachen ist ein sehr kleiner und sehr formbarer Rahmen, in dem Sie auf einfache Weise Dinge tun können, die in einer statischen Sprache viel komplizierter sind: verschiedene Formen von Affen-Patching, die zum Metaprogrammieren, Verspotten und Testen, dynamisches Ersetzen von Code usw. Smalltalk und Lisp, beide sehr dynamisch, haben es so weit gebracht, Umgebungsbilder zu versenden, anstatt sie aus dem Quellcode zu erstellen. Wenn Sie jedoch sicherstellen möchten, dass bestimmte Datenpfade typsicher sind, fügen Sie Zusicherungen hinzu und schreiben Sie weitere Komponententests.
quelle
In den meisten dynamischen Sprachen können Sie den Typ eines Objekts oder Werts zumindest dynamisch testen .
Für einige dynamische Sprachen gibt es statische Inferencer, Checker und / oder Enforcer: z
Und Perl 6 unterstützt ein optionales Typsystem mit statischer Typisierung.
Aber ich vermute, das Fazit ist, dass viele Leute dynamisch Sprachen benutzen, weil sie dynamisch getippt sind, und für sie ist die optionale statische Eingabe sehr "ho hum". Und viele andere Leute benutzen sie, weil sie "für Nicht-Programmierer leicht zu bedienen" sind, hauptsächlich als Folge der fehlerverzeihenden dynamischen Typisierung. Für sie ist die optionale Eingabe etwas, das sie entweder nicht verstehen oder nicht verwenden möchten.
Wenn Sie zynisch wären, könnten Sie sagen, dass die optionale statische Eingabe das Schlimmste aus beiden Welten bietet. Für einen Zealot mit statischem Typ werden nicht alle dynamischen Typfehler verhindert. Für einen dynamischen Fan ist es immer noch eine gerade Jacke ... obwohl die Träger nicht straff gespannt sind.
quelle
Javascript hat geplant, einige optionale statische Typisierungen einzuschließen, und es scheint, als würden viele ausgereifte dynamische Sprachen in diese Richtung gehen.
Der Grund dafür ist, dass Sie beim ersten Codieren schnell und dynamisch tippen möchten. Sobald Ihr Code solide ist, funktioniert und viele Verwendungszwecke hat, möchten Sie das Design sperren, um Fehler zu reduzieren. (Dies ist sowohl für Benutzer als auch für Entwickler von Vorteil, da erstere bei ihren Aufrufen eine Fehlerprüfung erhalten und letztere nicht versehentlich Fehler verursachen.
Das ergibt für mich einen Sinn, da ich zu Beginn eines Projekts in der Regel zu viel Typprüfung finde, zu wenig am Ende der Laufzeit, egal welche Sprache ich benutze;).
quelle
Python - Objekte machen eine Art haben.
Sie geben den Typ an, wenn Sie das Objekt erstellen.
Eigentlich ist eine manuelle Typprüfung in Python fast immer eine Verschwendung von Zeit und Code.
Es ist einfach eine schlechte Praxis, in Python Code für die Typprüfung zu schreiben.
Wenn ein unangemessener Typ von einem böswilligen Soziopathen verwendet wurde, lösen die gewöhnlichen Methoden von Python eine gewöhnliche Ausnahme aus, wenn der Typ nicht geeignet ist.
Sie schreiben keinen Code, Ihr Programm schlägt immer noch mit einem fehl
TypeError
.Es gibt sehr seltene Fälle, in denen Sie den Typ zur Laufzeit bestimmen müssen.
Da es sich nicht um eine "Einschränkung" handelt, ist die Frage keine echte Frage.
quelle
Meistens müssen Sie dies nicht tun, zumindest nicht in dem Detailgrad, den Sie vorschlagen. In PHP machen die Operatoren, die Sie verwenden, klar, was Sie von den Argumenten erwarten. Es ist jedoch ein bisschen konstruktiv, dass PHP Ihre Werte umwandelt, wenn dies überhaupt möglich ist, selbst wenn Sie ein Array an eine Operation übergeben, die eine Zeichenfolge erwartet. und das ist genau das, wo Typprüfungen sind nützlich). Ansonsten spielt es keine Rolle, ob Sie Ganzzahlen
1
und /5
oder Zeichenfolgen hinzufügen"1"
und"5"
- die bloße Tatsache, dass Sie die verwenden+
Der Operator signalisiert PHP, dass Sie die Argumente als Zahlen behandeln möchten, und PHP gehorcht. Eine interessante Situation ist, wenn Sie Abfrageergebnisse von MySQL erhalten: Viele numerische Werte werden einfach als Zeichenfolgen zurückgegeben, aber Sie werden es nicht bemerken, da PHP sie immer dann für Sie umsetzt, wenn Sie sie als Zahlen behandeln.Python ist in Bezug auf seine Typen etwas strenger, aber im Gegensatz zu PHP hatte Python von Anfang an Ausnahmen und verwendet sie konsequent. Das Paradigma "leichter um Verzeihung als um Erlaubnis zu bitten" schlägt vor, die Operation nur ohne Typprüfung auszuführen und sich auf eine Ausnahme zu verlassen, die ausgelöst wird, wenn die Typen keinen Sinn ergeben. Der einzige Nachteil, an den ich denken kann, ist, dass Sie manchmal feststellen werden, dass ein Typ nicht mit dem übereinstimmt, was Sie erwarten, aber es kann mühsam sein, den Grund dafür zu finden.
Und es ist ein weiterer Grund zu berücksichtigen: Dynamische Sprachen nicht haben eine Zusammenstellung der Bühne. Selbst wenn Sie Typeinschränkungen haben, können diese nur zur Laufzeit ausgelöst werden, weil keine Kompilierungszeit vorhanden ist . Wenn Ihre Prüfungen trotzdem zu Laufzeitfehlern führen, ist es viel einfacher, sie entsprechend zu modellieren: Als explizite Prüfungen (wie
is_XXX()
in PHP odertypeof
in Javascript) oder durch Ausnahmen (wie in Python). Funktionell haben Sie den gleichen Effekt (ein Fehler wird zur Laufzeit gemeldet, wenn eine Typprüfung fehlschlägt), aber er lässt sich besser in die übrige Semantik der Sprache integrieren. Es ist einfach nicht sinnvoll, Typfehler, die sich grundlegend von anderen Laufzeitfehlern unterscheiden, in einer dynamischen Sprache zu behandeln.quelle
Sie könnten an Haskell interessiert sein - das Typensystem leitet die Typen aus dem Code ab und Sie können auch Typen angeben.
quelle
Wie die anderen Antworten bereits angedeutet haben, gibt es beim Implementieren einer Programmiersprache zwei Ansätze für die Eingabe.
Beide Ansätze sind gültig und deren Verwendung hängt zum Teil von technischen Überlegungen wie der Leistung und zum Teil von politischen Gründen wie dem Zielmarkt für die Sprache ab.
quelle
Zuallererst sind dynamische Sprachen hauptsächlich für die Benutzerfreundlichkeit geschaffen worden. Wie Sie bereits erwähnt haben, ist es sehr gut, die Typkonvertierung automatisch durchzuführen und uns weniger Overhead zu bieten. Gleichzeitig mangelt es aber an Performance-Problemen.
Sie können bei den dynamischen Sprachen bleiben, wenn Sie sich nicht um die Leistung sorgen. Angenommen, JavaScript wird langsamer ausgeführt, wenn in Ihrem Programm viele Typkonvertierungen durchgeführt werden müssen, dies hilft jedoch, die Anzahl der Zeilen in Ihrem Code zu verringern.
Zu erwähnen ist, dass es auch andere dynamische Sprachen gibt, mit denen der Programmierer den Typ angeben kann. Beispielsweise ist Groovy eine der bekanntesten dynamischen Sprachen, die unter JVM ausgeführt werden. Und es ist sogar in den letzten Tagen sehr berühmt gewesen. Beachten Sie, dass die Leistung von Groovy mit der von Java identisch ist.
Hoffe es hilft dir.
quelle
Es macht einfach keinen Sinn, dies zu tun.
Warum?
Da das Typsystem von DTLs genau so ist, dass Typen zur Kompilierungszeit nicht bestimmt werden können. Daher konnte der Compiler nicht einmal prüfen, ob der angegebene Typ sinnvoll ist.
quelle
Schauen Sie sich Go an, auf der Oberfläche ist es statisch typisiert, aber diese Typen können Schnittstellen sein, die im Wesentlichen dynamisch sind.
quelle