Ähnliche Frage wurde auf SO geschlossen.
Manchmal stellen wir beim Programmieren fest, dass eine bestimmte Kontrollstruktur für uns sehr nützlich ist, aber nicht direkt in unserer Programmiersprache verfügbar ist.
Welche alternativen Kontrollstrukturen sind Ihrer Meinung nach eine nützliche Möglichkeit, die Berechnung zu organisieren?
Ziel ist es, neue Denkansätze für die Strukturierung von Code zu entwickeln, um Chunking und Argumentation zu verbessern.
Sie können eine wünschenswerte Syntax / Semantik erstellen, die derzeit nicht verfügbar ist, oder eine weniger bekannte Kontrollstruktur für eine vorhandene Programmiersprache angeben.
Die Antworten sollten Anregungen für eine neue Programmiersprache oder die Verbesserung einer tatsächlichen Sprache geben.
Stellen Sie sich das als Brainstorming vor. Stellen Sie also etwas auf, das Ihrer Meinung nach eine verrückte Idee ist, aber in manchen Szenarien durchaus machbar ist.
Es geht um zwingende Programmierung.
Antworten:
OK, das ist eine lustige Frage.
Ich hätte auch gerne einen General
else
für eine Weile und für Schleifen, wenn die Bedingung beim ersten Test nicht erfüllt ist :Dies vermeidet die umständliche Neuberechnung der Bedingung oder deren Speicherung in einer Variablen.
quelle
while ... else
Konstrukt den Weg Macneil beschreibt es zu PHP. Ich denke, es ist eine großartige Idee, denn das "Hier sind die Ergebnisse / Es gab keine Ergebnisse" ist eine ziemlich verbreitete Redewendung in Web-Apps.Warum nicht ein paar Antworten zu einer zusammenfügen?
Eine erweiterbare, verallgemeinerte Syntax für Flusssteuerungskonstrukte in einer imperativen Sprache wäre ziemlich nützlich und unterhaltsam. Bis das auftaucht, werde ich wohl nur Lisp oder so was benutzen.
quelle
seventh { ... }
.Kontrollstrukturen als Funktionen.
Ich will
for
,if
,else
,while
, etc. Funktionen sein, keine besonderen Strukturen.Ich möchte
return
,try/except
undgoto
Derivate von Fortsetzungen sein.Dies hat natürlich weniger mit einer bestimmten Kontrollstruktur zu tun als vielmehr damit, wie Sie Kontrollstrukturen im Allgemeinen sehen, die Meta von Kontrollstrukturen.
quelle
for
,if
,else
, undwhile
als Funktionen macht mich daraus schließen , dass die Parameter für diese Funktionen träge, um das gleiche wie die ursprünglichen Konstrukte verhalten ausgeführt werden müssen. Es wäre schön, die Fähigkeit zu haben, eine faule Hinrichtung durchzuführen.return
, Ausnahmen usw. Jetzt hat der erfahrene Programmierer ein leistungsfähiges zusätzliches Werkzeug in seiner Toolbox, falls dies erforderlich ist. Außerdem sollten IMHO-Sprachen nicht "niedergeschlagen" werden. Sprachen sollten in der Lage sein, das Fachwissen zu erweitern und das CS-Wissen zu erweitern.In dem verlinkten Artikel geht es definitiv um Donald Knuths N + 1/2-Loops . In C / C ++ / Java ausgedrückt:
Dies ist nützlich, um Zeilen oder Zeichen aus einer Datei zu lesen, um zu prüfen, ob Sie EOF erreicht haben, und um sie dann zu verarbeiten. Ich bin es so gewohnt, das Muster zu sehen
for(;;)..if(..)break;
, dass es für mich idiomatisch ist. (Bevor ich den Artikel von Knuth gelesen hatte, der im Buch Literate Programming abgedruckt war , war dieser ein "wtf?".)Knuth schlug die Schlüsselwörter vor
loop/while/repeat
:Wo
S
undT
sind Platzhalter für eine Reihe von null oder mehr Anweisungen undC
ist eine boolesche Bedingung. Wenn es keineS
Anweisung gäbe, wäre es eine while-Schleife, und wenn es keineT
Anweisung gäbe, wäre es eine do-Schleife.Dieses Konstrukt selbst könnte verallgemeinert werden, indem null oder mehr
while C
Klauseln zugelassen werden, was es perfekt macht, um Endlosschleifen und dann einige seltenere Bedingungen auszudrücken, die zwei Überprüfungen erfordern würden.Im selben Artikel schlug Knuth einen Signalisierungsmechanismus vor, der eine lokale Version von Ausnahmen für das Werfen / Fangen von Ausnahmen ist (als Alternative zur Verwendung von goto).
Für mich? Ich wünsche mir, dass Java die Tail-Call-Optimierung unterstützt, damit ich bei Bedarf eine allgemeine Kontrollstruktur ausdrücken kann .
Update: Ich habe vergessen zu erwähnen, dass viele C / C ++ / Java-Programmierer dieses Problem umgehen, indem sie eine eingebettete Zuweisung verwenden, unter der Bedingung, dass
while
:Unter Verwendung der Begriffe aus Knuths Konstrukt ist dies zulässig, wenn
S
undC
kann zu einem einzigen Ausdruck kombiniert werden. Einige Leute hassen es, die eingebettete Aufgabe oben zu sehen, während andere es hassen,break
diefor (;;)
oben genannte Aufgabe zu sehen . Aber wennS
undC
kann nicht kombiniert werden, beispielsweise wennS
mehrere Anweisungen hat, dasfor (;;)
ist die einzige Alternative , ohne Code zu wiederholen. Die andere Alternative besteht darin, denS
Code einfach zu duplizieren :Knuths
loop/while/repeat
Alternative scheint viel besser zu sein.quelle
repeat-until
Schleife sehr ähnlich .do while ... loop until
- sowohl die Vorbedingung als auch die Nachbedingung sind optional, und ich erinnere mich (vage), beide in einer Schleife verwendet zu haben. Für deine Kondition gibt es die Adaexit when ...;
. Der Hauptvorteil gegenüberif ... break;
ist, dass Sie schreiben können,exit loopname when ...;
um mehrere (aber nicht unbedingt alle) verschachtelte Schleifen gleichzeitig zu verlassen. Wahrscheinlich auch etwas sichtbarer als diese Pause.Die BCPL-Sprache hatte einen
valueof
Ausdruck , mit dem eine Folge von Anweisungen in einen einzelnen Ausdruck umgewandelt werden konnte:Wo
some series of statements
kann irgendetwas sein und das ganzevalueof
auswertenv
.Dies kann in Java nützlich sein, wenn Sie ein Argument für den Aufruf von a
this()
oder berechnen müssensuper()
(was voraussetzt, dass davor nichts passiert). Natürlich können Sie auch nur eine separate Methode schreiben, aber das kann schwierig sein, wenn Sie viele lokale Werte für den Kontext übergeben müssen.Wenn Sie
final
Variablen verwenden können, die benötigt werden, können Sievalueof
in Java bereits anonyme innere Klassen verwenden:quelle
({ statement1; statement2; ...; result-expr; })
. Ähnliches habe ich auch anderswo gesehen, aber ich weiß nicht mehr, wo. Wahrscheinlich alle von BCPL kopiert.macht dasselbe wie:
macht dasselbe wie:
quelle
unless
.In einem anderen Sinne würde ich mir eine bessere Unterstützung für Iteratoren in Programmiersprachen wünschen. Insbesondere, wenn Sie zwei Sammlungen paarweise durchsuchen möchten :
Einige dynamische Sprachen haben dies möglicherweise bereits oder können problemlos über Bibliotheken und Makros unterstützt werden, aber ich denke, dies liegt im Geiste Ihrer Frage.
Wenn die beiden Mengen nicht die gleiche Größe haben, kann es zu einer Ausnahme kommen, oder Sie können
else
nach der Schleife eine Meldung anzeigen, dass ein Größenunterschied vorliegt.Sie können dies natürlich verallgemeinern, indem Sie drei oder mehr Listen durchgehen.
Update: Auch nützlich wäre es, das kartesische Produkt zwischen iterablen zu machen:
Das wäre nichts anderes als verschachtelte Schleifen:
Ich bin ein wenig besorgt, dass zwischen den beiden Notationen, die ich hier angegeben habe, ein Unterschied in der Anzahl der Paare zwischen O (n) und O (n ^ 2) besteht, mit nur der Änderung eines einzelnen Zeichens.
quelle
for a, b, c in itertools.product(iter1, iter2, iter3):
gibt Ihnen das kartesische Produkt faul bewertet. Was ist das? Sie möchten auch Permutationen und Kombinationen eines bestimmten Iterators?itertools.permutations
,itertools.combinations
.Es gibt sogenannte "Dijkstra's Loop" (auch "Dijkstra's Guarded Loop" genannt). Es wurde in der Guarded Command Language (GCL) definiert . Informationen zu Syntax und Semantik finden Sie im obigen Wikipedia-Artikel in Abschnitt 6 Repetition: do .
Heutzutage kenne ich tatsächlich eine Programmiersprache, die dieses Kontrollmuster direkt unterstützt. Es ist Oberon-07 (PDF, 70 KB). Und es unterstützt "Dijkstra's Loop" in Form einer while-Anweisung. Schauen Sie sich Abschnitt 9.6 an. Während Aussagen im obigen PDF.
PS Dies ist eine Kopie meiner SO-Antwort .
quelle
Icon-ähnliche Ausdrücke mit integriertem Backtracking.
Python profitiert von vielen Vorteilen des Icon-Generators - und macht dies im Allgemeinen besser, IMO. Und im Prinzip war das Backtracking nur eine Art Ausnahmewurf, aber es war die Einfachheit der Ausdrücke, die grobe Entsprechung von ...
Fehlerfälle wie Division durch Null zu behandeln.
Wo Icon durchgedreht ist - keine Vergleichsoperatoren, die Boolesche Werte zurückgeben. Die Vergleiche waren immer erfolgreich oder haben ein Zurückverfolgen ausgelöst, und es gab ein anderes semantisches Problem, an das ich mich jetzt verzweifelt zu erinnern versuche.
Ich habe immer gedacht, sie sollten einen
if
Ausdruck haben, der nichts anderes enthältif (condition, success-value)
, und zurückverfolgen, wenn die Bedingung falsch ist - und die seltsamen Vergleiche fallen lassen.EDIT Ich erinnere mich - offensichtlich wirklich. Ein Vergleich mit zwei Argumenten ist entweder erfolgreich oder schlägt fehl - es wird kein neuer zurückzugebender Wert berechnet. Also, wenn es gelingt, was kehrt es zurück? Antwort - eines der Argumente. Aber wenn Sie schreiben
a > b
, welches ist das logische Argument, um zurückzukehren -a
oderb
? Und wenn dub < a
stattdessen schreibst ? Ich denke, es hat immer das richtige Argument geliefert, was genauso viel Sinn macht wie alles andere, aber es schien mir immer noch das falsche Argument zu sein.quelle
Dies ist nur eine allgemeine Idee und Syntax:
AUCH Bedingung wird immer ausgewertet. ELSE funktioniert wie gewohnt.
Es funktioniert auch für den Fall. Wahrscheinlich ist es eine gute Möglichkeit, die break-Anweisung zu eliminieren:
kann gelesen werden als:
Ich weiß nicht, ob dies nützlich oder einfach zu lesen ist, aber es ist ein Beispiel.
quelle
Continuation Passing Style fällt mir ein. Dann möchten Sie natürlich auch Tail Call Optimization haben .
quelle
goto return ...;
Anweisung geben, die die Absicht hat, einen Tail-Call explizit auszuführen. Wenn der Compiler ihn also nicht iterativ ausführen kann, handelt es sich um einen Fehler.Die nahtlose Thread-Verzweigung hat eine Syntax wie eine Funktion, wird jedoch in einem separaten Thread ausgeführt und kann nicht auf Daten zugreifen, die ursprünglich nicht an ihn übergeben wurden.
Wenn ein Zweig aufgerufen wird, wird sofort ein Handle zurückgegeben.
Mit dem Handle kann überprüft werden, ob die Aufgabe erledigt ist.
Wenn das Ergebnis angefordert wird, bevor die Ausführung abgeschlossen ist, wartet der Haupt-Thread einfach.
Dies würde nicht die fortgeschritteneren Multithreading-Szenarien abdecken, sondern eine leicht zugängliche Möglichkeit bieten, mehrere Kerne zu nutzen.
quelle
handle.finished()
Test, aberspawn
undsync
alles , was Sie für 90% der parallelen Programmieraufgaben benötigen.Der Block FIRST und THEN wird ausgeführt, wenn eine der drei Bedingungen als wahr ausgewertet wird. Der ERSTE Block wird vor dem bedingten Block ausgeführt, und DANN wird ausgeführt, nachdem der bedingte Block ausgeführt wurde.
ELSE bedingte oder endgültige Schreibvorgänge nach der Anweisung FIRST und THEN sind von diesen Blöcken unabhängig.
Es kann lauten:
Diese Funktionen sind nur ein Formular zum Lesen. Sie würden keinen Spielraum schaffen. Es ist eher ein Gosub / Return von Basic.
Nützlichkeit und Lesbarkeit als Diskussionsgegenstand.
quelle
Manchmal schreibe ich eine Schleife, die während der ersten Iteration etwas anderes machen muss. Beispiel: Anzeigen von <th> -Tags anstelle von <td> -Tags.
Ich behandle diese Situation mit einer Booleschen Flagge. Etwas wie das:
Es erscheint dumm, den Wert
first
jeder Iteration zu überprüfen, wenn er die meiste Zeit falsch sein wird.Ich hätte gerne eine Loop-Option, um bei der ersten Iteration einen anderen Loop-Body anzugeben. Es wäre keine separate Variable erforderlich. Der kompilierte Code würde auch keinen benötigen, da der generierte Code zwei Körper haben würde, einen für die erste Iteration und einen für den Rest.
quelle
print(out, first "<th>" then "<td>")
if (!first) gimme-a-comma ();
aber fast dasselbe. Ein Einwand, den ich allerdings haben würde - wenn Sie es richtig zusammenfassen, erhalten Sie Dinge wie die Python-String-Join-Methode -, obwohl Sie oft das Grundmuster benötigen, muss die zugrunde liegende Schleife nicht so oft umgeschrieben werden.if (!first)
, aber Mikrooptimierer können Einwände gegen die Verzweigungsvorhersage erheben.if (!first)
, einen optimierenden Compiler zu verwenden und entscheiden zu lassen, ob der Schleifenkörper klein genug ist, um sich abzuwickeln und loszuwerden,first
ist ein Nettogewinn.[kopiert von meiner eigenen Antwort auf stackoverflow]
ignoring
- Um Ausnahmen zu ignorieren, die in einem bestimmten Codeblock auftreten.Mit einem ignorierenden Kontrollkonstrukt könnten Sie es übersichtlicher und lesbarer schreiben als:
[Scala stellt dieses (und viele andere Ausnahmebehandlungs-Steuerungskonstrukte) in seiner Standardbibliothek im Paket util.control zur Verfügung. ]
quelle
try..catch
Block ist eine Sache; es zwingt Sie, den Fehler zu erkennen und ihn absichtlich zu ignorieren; Das Werfen von Codestücken unter einem globalen Ignorieren kann zu Problemen führen, wenn diese Ausnahmen ausgelöst werden, und zu schlechten Programmiergewohnheiten.try
Block, nur werden die Ausnahmen aufgelistet, die er abfängt und ignoriert, anstatt später. Dies könnte sogar einen Vorteil für die Lesbarkeit bedeuten - z. B. den Leser wissen lassen, dass eine fehlende Datei kein Fehler ist, noch bevor er den offenen Aufruf liest.Anstatt von:
Mach es mit Python oder jetzt auch mit C #:
Scala hat viele neue Funktionen.
Schließlich können Sprachen wie Clojure erweitert werden, um die zusätzliche Funktionalität bereitzustellen.
quelle
Ich habe zwei Ideen.
Oft stelle ich fest, dass ich mich in
catch
Blöcken wiederhole . Dies kann etwas durch Extrahieren von Methoden geholfen werden, aber dies kann zu unnötigem Durcheinander führen, wenn die Methoden sehr kurz sind oder anderweitig keine Methode wert sind. Es wäre also schön,catch
Blöcke zu verschachteln :In der Web-Programmierung tue ich oft so etwas (dies ist kein wirkliches Beispiel, also analysiere keine fiktiven Fälle):
In Javascript (naja, ECMAScript und vielleicht anderen, mit denen ich nicht vertraut bin)
||
kann es helfen , da jeder Wert als Bedingung bewertet werden kann.Ich mag es wirklich, wie das aussieht, und ich wünschte, mehr Sprachen, insbesondere einige auf der Serverseite, hätten Unterstützung dafür. (PHP kann alles als Bedingung auswerten, konvertiert aber den gesamten Bedingungsausdruck in einen Booleschen Ausdruck, anstatt den Wert beizubehalten. Ich weiß nicht, wie Python oder Ruby aussehen.) Nach drei oder mehr Fällen könnte es unhandlich werden, aber wenn Sie mehr haben In mehr als drei Fällen liegt möglicherweise auch ein fehlerhaftes Software-Design vor.
quelle
x if c else y
Syntax, ein wichtiger Grund , das war geschehen , weil eine Menge von Ausdrücken dieser Semantik für die Verwendung||
und&&
war auf subtile Weise Buggy. IIRC Ein häufiger Fall war ein Wert (z. B. Null), der für die zu behandelnde Anwendung gültig warfalse
und daher verworfen wurde, sodass stattdessen ein ungültiger Fallback verwendet wurde. Allerdings - siehe meine Antwort WRT der Icon-Programmiersprache, die Ausdrücke wie haben kannget1() else get2() else default
.Der verallgemeinerte Schalter hat oben gesagt:
In Haskell:
quelle
In C # möchte ich einfache
switch () { ... }
, aber mit solchen Ausdrücken erweiterbare verwenden:Und so weiter. Das gleiche mit Zahlen oder anderen Typen (dh Träger
IComparable
,IConvertible
...)Dies könnte meinen Code lakonischer und lesbarer machen.
quelle
Es ist eine lustige Frage, wie @Macneil sagte.
Meine ungewöhnliche Lieblingskontrollstruktur, die ich (demütiger Husten) entdeckt habe, ist die differentielle Ausführung .
Es hat bestimmte Verwendungen. Die überwältigende Verwendung besteht für mich in der Programmierung von Benutzeroberflächen, was ein Beispiel für das allgemeinere Problem ist, redundante Daten in Übereinstimmung zu halten. Auf der einen Seite gibt es Anwendungsdaten und auf der anderen Seite gibt es Benutzeroberflächen-Steuerelemente, die in Übereinstimmung gehalten werden müssen. Das klingt nach "Bindung", aber es steckt noch viel mehr dahinter.
Normalerweise implementiere ich es durch Makros in C oder C ++. In C # muss ich es durch handexpandierende Anweisungen tun. Das ist ein Schmerz, aber es funktioniert.
Einmal habe ich es in Form von Lisp-Makros implementiert und dann war es sehr sauber. Es erforderte keine Sorgfalt seitens des Programmierers. Ich hätte das Gleiche in jeder anderen strukturierten Sprache tun können, wenn ich mir die Mühe gemacht hätte, einen vollständigen Parser zu schreiben und dann alles Richtige zu generieren. Das ist ein großes Projekt, und ich habe es nicht getan.
quelle
Bei "traditionellen" Kontrollstrukturen geht
for
es darum, den Arbeiter zu kontrollieren und ihn den korrupten Ideologien der herrschenden kapitalistischen Elite zu unterwerfen. Deshalb verwende ichph0r
stattdessen alternative Kontrollstrukturen wie . Es ist wiefor
, aber radikaler: Sie werden es nicht fangenph0r
, einen Anzug und eine Krawatte zu tragen, die etwas Corporate BS ausstoßen.ph0r
hält es echt, Mann.Kämpfe gegen die Macht!
quelle
Einfachstes
for
Loop-quelle