In letzter Zeit bin ich immer frustrierter geworden, dass es in den meisten modernen Programmiersprachen, mit denen ich gearbeitet habe (C / C ++, C #, F #, Ruby, Python, JS und mehr), kaum Sprachunterstützung gibt, um festzustellen, was Ein Unterprogramm reicht tatsächlich aus.
Betrachten Sie den folgenden einfachen Pseudocode:
var x = DoSomethingWith(y);
Wie bestimme ich, was der Aufruf von DoSomethingWith (y) tatsächlich bewirkt ? Wird es y mutieren oder wird es eine Kopie von y zurückgeben ? Hängt es vom globalen oder lokalen Zustand ab oder ist es nur von y abhängig ? Wird es den globalen oder lokalen Staat verändern? Wie wirkt sich die Schließung auf das Ergebnis des Anrufs aus?
In allen Sprachen, auf die ich gestoßen bin, kann fast keine dieser Fragen durch bloßes Betrachten der Signatur des Unterprogramms beantwortet werden, und es gibt fast nie Unterstützung für die Kompilierung oder Laufzeit. Normalerweise besteht die einzige Möglichkeit darin, dem Autor der API Ihr Vertrauen zu schenken und zu hoffen, dass die Dokumentations- und / oder Namenskonventionen zeigen, was die Unterroutine tatsächlich tut.
Meine Frage lautet: Gibt es heute Sprachen, die symbolisch zwischen diesen Arten von Szenarien unterscheiden und die Einschränkungen für die Kompilierungszeit für den Code festlegen, den Sie tatsächlich schreiben können?
(Natürlich gibt es in den meisten modernen Sprachen eine gewisse Unterstützung dafür, wie z. B. unterschiedliche Ebenen des Umfangs und der Schließung, die Trennung zwischen statischem Code und Instanzcode, Lambda-Funktionen usw. Aber zu oft scheinen diese miteinander in Konflikt zu geraten. Beispielsweise ist eine Lambda-Funktion normalerweise entweder rein funktional und gibt einfach einen Wert zurück, der auf Eingabeparametern basiert, oder mutiert die Eingabeparameter auf irgendeine Weise. In der Regel ist es jedoch möglich, über eine Lambda-Funktion auf statische Variablen zuzugreifen, was wiederum möglich ist Geben Sie Zugriff auf Instanzvariablen, und dann bricht alles auseinander.)