@Aries:
Noch was zur Historie: In den imperativen Sprachen gab es
schon immer for-Schleifen. Die Idee basiert auf
Gottlob FregesKomprehensionsschema. Frege war einer der zwei Erfinder der modernen Logik. Der andere war
Charles Sanders Peirce. Eine Menge ist vollständig definiert, wenn ich ihre Elemente angeben kann. Zwei Mengen, die genau dieselben Elemente beinhalten, sind dieselbe Menge. Man nennt das das Extensionalitätsprinzip. Man schreibt dann zB. so etwas wie {x | f(x) == 0}, das wäre dann die Menge aller x für die f(x) gleich 0 ist. Man kann das auch erweitern: {x*2+3 | f(x) == 0} ist die Menge aller x*2+3 für die f(x) gleich 0 ist. Das wurde in der Funktionalen Programmierung auf Listen übertragen: [x*2+3 | f(x) == 0].
Phil "Lambdaman" Wadler hat dafür die Bezeichnung Listenkomprehension eingeführt. Man findet sie in Haskell und in Python. Die for-Schleife, auch wenn sie historisch viel früher da war, kann man als Erweiterung davon absehen, die es ermöglicht, nicht nur Ausdrücke (Expressions) auszuwerten, sondern auch Befehle (Statements) auszuführen:
Und nochwas zur Pragmatik der Benennungen: Ziel sollte es IMO sein, einen übersichtlichen, lesbaren Code zu erzeugen, nicht an jeder Mikrostelle für ultimative logische Konsistenz zu sorgen. Nicht nur wäre letzteres Zeitverschwendung, sondern widerspräche auch auch dem Geist und der Praxis der Logik. Diese ist zuerst einmal ein System, um nützliche formale Beschreibungen für tatsächliche Sachverhalte zu erzeugen und aus diesen, mittels syntaktischer Umformungen, Ableitungen (AKA: Beweise) durchzuführen. Für die Gültigkeit einer Ableitung ist die Benennung unerheblich. Eine gute Benennung hilft einem aber dabei, den Beweis einfacher/schneller verstehen zu können. Genauso ist es beim Programmieren (wg. der
Curry-Howard-Korrespondenz?

. Beweise und Programme funktionieren wg. ihrer Semantik, also dem, was Compiler oder Interpreter verstehen, aber nicht wg. der Benennungen. Letztere sind wichtig für diejenigen, die mit dem Source Code arbeiten, und zwar für den Leser noch mehr, als den Scheiber, da Programme öfter gelesen, als geschrieben werden. Die Maxime sollte also sein, es dem Leser möglichst einfach zu machen. Und da wie gesagt die Benennungen unerheblich sind für die Semantik eines Programms, sollte man sich auch nicht damit aufhalten, vermeintlich logische Ungenauigkeiten in den Benennungen zu eliminieren, da diese eben mir der Logik gar nichts zu tun haben, sondern nur mit der Lesbarkeit.
Dein Denken scheint mir hier ein bischen verquer. Du stellst Prinzipien auf, nach denen du Sachen benennst, oder überhaupt programmierst, die du zwar begründest, aber die Begründungen setzt du absolut, ohne sie weiter zu hinterfragen. Mich erinnert das an die Anekdote von Wittgenstein, der seine Studenten in Cambridge einmal fragte, warum man denn sage, die Sonne gehe auf bzw. unter, obwohl wir doch wissen, dass sich die Erde um sie Sonne dreht, und nicht umgekehrt. Jemand antwortete darauf: Naja, es sieht halt so aus. Worauf Wittgenstein erwiderte: Wie sähe es aus, wenn es anders wäre? Also, mit meinen Worten: Wie müsste es aussehen, damit es so aussähe, als drehte sich die Erde um die Sonne? Tip: genauso. Der Unterschied liegt also nicht im Aussehen, sondern in der eingenommenen Perspektive, und genauso ist es auch beim Programmieren: wenn meine Perspektive die Mikro-Perspektive ist, dass jedes Mikro-Element (zB. Namen) mit allem anderen logisch konsistent zu sein hat (obwohl es, wie gesehen, mit Logik gar nichts zu tun hat), dann bin ich blind für andere Perspektiven und Begründungen. Mir hat es jedenfalls geholfen, mich beim Programmieren stets zu fragen: Wie wär's, wenn's anders wär? Oder, wie
Alan Kay es ausdrückt:
A change in perspective is worth 80 IQ points.
In specifications, Murphy's Law supersedes Ohm's.