Ich habe solche Aussagen nie verstanden. Um ehrlich zu sein, selbst wenn Sie den Rückgabetyp einer Funktion deklarieren, können und werden Sie ihn vergessen, nachdem Sie viele Codezeilen geschrieben haben, und Sie müssen immer noch zu der Zeile zurückkehren, in der sie mit der Suchfunktion von deklariert wurde Ihr Texteditor, um es zu überprüfen.
Es geht nicht darum, dass Sie den Rückgabetyp vergessen - das wird immer passieren. Es geht darum, dass das Tool Sie darüber informieren kann, dass Sie den Rückgabetyp vergessen haben.
Da Funktionen mit Typ deklariert sind funcname()...
, müssen Sie ohne Kenntnis des Typs jede Zeile durchsuchen, in der die Funktion aufgerufen wird, da Sie nur wissen funcname
, während Sie in Python und dergleichen nur suchen können def funcname
oder function funcname
was nur einmal vorkommt bei der Erklärung.
Dies ist eine Frage der Syntax, die völlig unabhängig von der statischen Typisierung ist.
Die Syntax der C-Familie ist in der Tat unfreundlich, wenn Sie eine Deklaration nachschlagen möchten, ohne über spezielle Tools zu verfügen. Andere Sprachen haben dieses Problem nicht. Siehe Rusts Deklarationssyntax:
fn funcname(a: i32) -> i32
Darüber hinaus ist es bei REPLs trivial, eine Funktion auf ihren Rückgabetyp mit verschiedenen Eingaben zu testen, während Sie bei statisch typisierten Sprachen einige Codezeilen hinzufügen und alles neu kompilieren müssen, um den deklarierten Typ zu kennen.
Jede Sprache kann interpretiert werden und jede Sprache kann eine REPL haben.
Wie ist statische Typisierung in größeren Projekten wirklich hilfreich, außer den Rückgabetyp einer Funktion zu kennen, die eindeutig keine Stärke statisch typisierter Sprachen ist?
Ich werde abstrakt antworten.
Ein Programm besteht aus verschiedenen Operationen, und diese Operationen sind aufgrund einiger Annahmen, die der Entwickler trifft, so angeordnet, wie sie sind.
Einige Annahmen sind implizit und andere explizit. Einige Annahmen betreffen eine Operation in ihrer Nähe, andere eine Operation außerhalb von ihnen. Eine Annahme ist leichter zu identifizieren, wenn sie explizit und so nah wie möglich an den Stellen ausgedrückt wird, an denen ihr Wahrheitswert wichtig ist.
Ein Fehler ist die Manifestation einer Annahme, die im Programm vorhanden ist, aber in einigen Fällen nicht gilt. Um einen Fehler aufzuspüren, müssen wir die falsche Annahme identifizieren. Um den Fehler zu beseitigen, müssen wir entweder diese Annahme aus dem Programm entfernen oder etwas ändern, damit die Annahme tatsächlich gilt.
Ich möchte Annahmen in zwei Arten einteilen.
Die erste Art sind die Annahmen, die abhängig von den Eingaben des Programms gelten können oder nicht. Um eine fehlerhafte Annahme dieser Art zu identifizieren, müssen wir im Raum aller möglichen Eingaben des Programms suchen. Mit fundierten Vermutungen und rationalem Denken können wir das Problem eingrenzen und auf viel kleinerem Raum suchen. Da ein Programm jedoch nur ein wenig wächst, wächst sein anfänglicher Eingaberaum mit einer enormen Geschwindigkeit - bis zu dem Punkt, an dem es für alle praktischen Zwecke als unendlich betrachtet werden kann.
Die zweite Art sind die Annahmen, die definitiv für alle Eingaben gelten oder definitiv für alle Eingaben falsch sind. Wenn wir eine solche Annahme als falsch identifizieren, müssen wir nicht einmal das Programm ausführen oder Eingaben testen. Wenn wir eine solche Annahme als richtig identifizieren, müssen wir uns um einen Verdächtigen weniger kümmern, wenn wir einen Fehler (einen beliebigen Fehler) aufspüren . Es ist daher sinnvoll, möglichst viele Annahmen zu dieser Art zu haben.
Um eine Annahme in die zweite Kategorie einzuteilen (immer wahr oder immer falsch, unabhängig von Eingaben), benötigen wir eine Mindestmenge an Informationen, um an dem Ort verfügbar zu sein, an dem die Annahme getroffen wird. Im gesamten Quellcode eines Programms werden Informationen ziemlich schnell veraltet (zum Beispiel führen viele Compiler keine Interprocedural-Analyse durch, was jeden Aufruf zu einer harten Grenze für die meisten Informationen macht). Wir brauchen eine Möglichkeit, die erforderlichen Informationen aktuell zu halten (gültig und in der Nähe).
Eine Möglichkeit besteht darin, die Quelle dieser Informationen so nah wie möglich an dem Ort zu haben, an dem sie konsumiert werden sollen. Dies kann jedoch für die meisten Anwendungsfälle unpraktisch sein. Eine andere Möglichkeit besteht darin, die Informationen häufig zu wiederholen und ihre Relevanz im gesamten Quellcode zu erneuern.
Wie Sie bereits erraten können, sind statische Typen genau das - Beacons mit Typinformationen, die über den Quellcode verteilt sind. Diese Informationen können verwendet werden, um die meisten Annahmen über die Typkorrektheit in die zweite Kategorie aufzunehmen, was bedeutet, dass fast jede Operation in Bezug auf die Typkompatibilität als immer korrekt oder immer falsch klassifiziert werden kann.
Wenn unsere Typen falsch sind, spart uns die Analyse Zeit, indem wir den Fehler eher früh als spät auf uns aufmerksam machen. Wenn unsere Typen korrekt sind, spart uns die Analyse Zeit, indem sichergestellt wird, dass wir bei Auftreten eines Fehlers Tippfehler sofort ausschließen können.