@str1442: Man kann nicht alle Python-Anweisungen durch "statisches Ersetzen" beseitigen. ``for``/``while``-Schleifen deren Wiederholungen nicht statisch ermittelt werden können und ``if``/``else``, sowie Ausnahmebehandlung müssen mindestens erhalten bleiben, sonst kann man keine brauchbaren Programme schreiben. Die kann man letztendlich unter dem Begriff "bedingte Sprunganweisungen" zusammenfassen. Und das ist *Programmlogik* und nicht irgend etwas was nichts mit dem Programm sondern nur der Sprache zu tun hat.
Bei Assembler hängst Du mich komplett ab. Versuch mal ein Assemblerprogramm ohne Anweisungen zu schreiben. Das geht gar nicht, also kann man sie nicht von der Programmlogik trennen.
Das hab ich ja auch nie gesagt. Ich habe Assembler nur als Beispiel herangezogen, weil man dort eben außer einfachen Anweisungen gar nichts machen kann. Zumindest manuell. Sollte illustrieren, das Funktionen genauso wie Klassen nicht since creation vorhanden waren. Damit wollte ich klar machen, das eine Funktion ein eigenes Unterprogramm ist, und es sehr wohl von der Sprache abhängt, ob man überhaupt eine Funktion nutzen kann. Ohne Anweisungen (und damit Assembler-"Sprachfunktionen"; ich sag gleich was dazu) keine Funktionen, was ist also bei so einer Sprache die Funktion und wie lässt sie sich von einer "Anweisung" (was auch immer Sprache xyz sich genau dadrunter vorstellt) unterscheiden?
Zu Assembler selber: Wie du selbst sagst, greift Assembler direkt auf die "Hardwareebene" zu. Im Grunde ist Assembler eine Art Wrapper für die Hardwarefunktionen. Alle Anweisungen in Assembler greifen also direkt auf die Hardware und deren Funktionen zu, und abstrahieren somit mittels Anweisungen etwas von der Hardware.
Man stelle sich diesen Ansatz ein wenig erweitert vor: Angenommen, die Hardware könnte If Anweisungen sowie while / for Anweisungen ausführen. Mittels Anweisungen verschafft man sich einen Zugriff dadrauf. Genauso verstünde die Hardware das Konzept der Funktion.
Jetzt würde man Anweisungen für Hardwaretätigkeiten nutzen. Logik selber aber wären Funktionen, die mittels Anweisungen ja wieder implementiert werden. Diese Funktionen werden wiederrum in anderen Funktionen genutzt usw.
Würde man nun versuchen, zum Zweck der Generalisierung, diese Anweisungen selber in Funktionen zu legen, würde man intern ein Feature der Hardware (nämlich Funktionen) benutzen, um auf ein anderes zuzugreifen. Verletzt das nicht ziemlich stark die Abstraktion? Grade bei so generellen Dingen wie if, for, while?
Wenn Funktionen also in jeder Sprache (die das Funktionskonzept beherrscht) aus anderen Funktionen bestehen, bis man schließlich auf der niedrigsten Ebene irgendwenn ankommt (oder, wie Python es tut, andere Sprachen nutzt), so sind diese Funktion pure Logik *wenn* die genutzten Anweisungen (als Sprach "Features") nicht selber durch diese Logik dargestellt werden (als Funktionen). Wenn das der Fall ist, mag das nicht sonderlich tragisch sein, aber dann sind Sprache und Logik miteinander verbunden.
Ich weiss aber auch nicht was es jetzt bringt eine Anweisung durch eine andere zu ersetzen.
Pratisch (bis auf eventuell klarere Struktur usw) nichts. Weil man ja die Logik aquivalent bleibt (im Optimalfall). Theoretisch aber nutzt man damit ein Feature der Sprache, kann aber die Logik noch aquivalent implementieren. Diese ist ja selbst nichts weiter als in eine Struktur gequetschte Sequenz von Anweisungen, und die Struktur kann man austauschen, wie ich auch zuerst Milch in den Kaffee wie umgedreht schütten kann. Bestenfalls kommts aufs gleiche raus. Funktionen sind teil dieser Struktur. Würde ich diese Zugriffe auf Sprach Features (darauf läuft ja schlussendlich alles hinaus; und eine Ebene tiefer eben Zugriffe auf Hardware Funktionen, verschiebe in Register A, etc...) in Funktionen einlegen, ziehe ich mich doch praktisch "mit der eigenen Hand aus dem Sumpf".
Dagegen kann man es auch wie Io machen. Unterschied: Das geht nur auf "High-Level Ebene". Wie bei dem Beispiel mit dem Hardwarezugriff auf If und co kann man Sprachen erst ab einer bestimmten Ebene so gestalten, das es Exception Objekte gibt. Vermutlich, weil sie intern selbst auf eine andere Sprache und deren Anweisungen zurück greift, wenn ich zb eine Nachricht an ein Exception Objekt schicke. Ist aber nur meine Vermutung, die sich grade spontan ergeben hat.
Trotzdem kann man es auf die eine oder andere Art und Weise machen, was auch völlig ok ist. Anweisungen sind in "höheren" Sprachen natürlich etwas einschränkend und aus dem Design fallend, andererseits grenzen sie die Sprache von der Logik ab.
In Python kann man `goto` übrigens mit Ausnahmen nachbauen (
http://entrian.com/goto/) und es sieht fast aus wie eine Anweisung. Smile
. Hab es mir mal angeschaut, ist aber nicht mit Ausnahmen gebaut (was mich auch gewundert hätte; man kann ja wirklich einfach "goto" wie ein Statement nutzen), sondern indem es direkt auf stdout zugreift und auf "goto" als String reagiert. Empfinde ich als unsauber; aber goto hat es auch nicht besser verdient
Deine Aufteilung in Python von Funktionen -> Programmlogik und Anweisung -> Sprachtätigkeiten die mit der Programmlogik nichts zu tun haben, hält bei bedingten Sprüngen nicht Stand.
Ja, man kann nicht ohne Anweisungen arbeiten. Insofern haben Anweisungen etwas mit der Logik zu tun, ja. Aber wie ich schon sagte: Es sind Sprach Tätigkeiten. Sie sind die "einfachste" Ebene, und if (+ den rest den man für einen if vergleich braucht) alleine vermag auch keine Wunder zu vollbringen. Insgesamt aber stellt die Sprache die Struktur für Logik bereit; die Logik wiederrum baut sich aus sich selber auf, also anderen Objekten / Funktionen / whatever. Auf der unteresten Ebene stehen Statements (und Speichermöglichkeiten). Insofern hatte ich Unrecht (bzw mich unklar ausgedrückt). Aber: Das wichtige ist, das all das nur Struktur ist, die die Sprache bereitstellt. Die eigentliche Logik sind ja pure Gedanken, um es so zu sagen. Diese bauen sich aus den einfachsten Dingen auf. Diese Dinge sollten aber klar austauschbar sein; manchmal auch nicht vorhanden. All das fügt sich dann in eine Struktur ein, die die Sprache definiert (Funktionen, ...). Aber man könnte theoretisch das ganze Gestrüpp auch in zb BASIC oder Assembler schreiben. Füge ich nun dinge wie "for" direkt als Funktion ein, zwänge ich die einfachste Logik (die keine Gedankenlogik ist; sondern eben "Boolsche-Logik" - einfachste Dinge eben) in diese Sprach Struktur (Funktion) rein, ist das bei höheren Sprachen erstmal in Ordnung. In dem Moment verbinde ich aber die Logik mit der tieferliegenden, einfachen Logik, indem ich die einfache Logik ja selber wieder als Gedankenlogik sehe, die in diese Sprachstruktur reingepresst gehört.
Wo fangen bei Dir Sprachinterna an und was ist direkter Zugriff darauf?
Alles, was in die Programmlogik der Sprache selber gehört, ist ein Sprachinterna. Alles, was kein Sprachinterna ist, ist folglich in die von der Sprache festgelegte Struktur eingebettet.
Ob ich nun eine ``raise``-Anweisung verwende oder eine `raise`-Methode ist doch egal, ich habe in beiden Fällen nichts mit der Implementierung zu tun, die ein Sprachentwickler geschrieben hat.
Ist ja auch so, ist nur ein anderer Herangehensweg.
Ich sehe auch grade einen Denkfehler von mir: ein Exception Objekt ist in der eigenen Sprache mindestens dargestellt, beugt sich also der Struktur der Sprache. Insofern ist eine Methode darauf auch ein gangbarer Weg. Aber irgendwo ist auch da die Grenze zwischen Sprachen-Logik und deren Struktur, sowie der von ihr für die neue, in ihr geschrieben Sprache, definierte Struktur, in die man dann "Gedankenlogik" einbettet. Je weiter man sich öffnet, desto näher kommt man dadran heran.
Entweder man bricht mit der Struktur seiner Sprache oder man versucht, fundamentale Dinge dieser Struktur in die eigene Struktur hineinbringen. Was ja auch mittels Abstraktion funktioniert, wodurch man halbwegs oberflächlich auf der Api der Sprache operieren kann... Ich glaube, ich habe die ganze Zeit von zwei verschiedenen Dingen gesprochen
Nun, dennoch, irgendwo ist der Punkt, an dem sich eine Sprache "selber auf dem Sumpf ziehen müsste", würde man Anweisungen in die Sprachstruktur reinzwängen. Je tiefer (näher an Hardware Ebene) man geht, desto näher ist man diesem Punkt.
Ich habe das nun alles so aufgeschrieben, wie es mir in die Gedanken kam. Da ich aktuell aber erstmal genug habe, poste ichs so.
EDIT:
Wo ich grade bei Hardware und deren Funktionen war: Gibts da eigentlich eine ganz gute Beschreibung zu, wie das in etwa funktioniert? Also nicht das Nullen und Einsen für An / Aus zeug, sondern wie konkret spricht Assembler die Hardware an? Und wie wird in Maschinencode eine Endlosschleife dargestellt? Würde mich interessieren.