Une question similaire a été close sur SO.
Parfois, lorsque nous programmons, nous constatons qu'une structure de contrôle particulière nous serait très utile, mais n'est pas directement disponible dans notre langage de programmation.
Selon vous, quelles structures de contrôle alternatives sont un moyen utile d'organiser le calcul?
Le but ici est d'obtenir de nouvelles façons de penser la structuration du code, afin d'améliorer le découpage et le raisonnement.
Vous pouvez créer une syntaxe / sémantique à souhait non disponible actuellement ou citer une structure de contrôle moins connue sur un langage de programmation existant.
Les réponses devraient donner des idées pour un nouveau langage de programmation ou pour améliorer un langage réel.
Considérez cela comme un remue-méninges, alors postez quelque chose que vous pensez être une idée folle, mais cela peut être viable dans certains scénarios.
Il s'agit d'une programmation impérative.
Réponses:
OK, c'est une question amusante.
Je voudrais également avoir un général
else
pour les boucles while et for, lorsque la condition n'est pas vraie lors du premier test:Cela évite le recalcul maladroit de la condition ou son stockage dans une variable.
la source
while ... else
construction de la façon dont Macneil la décrit à PHP. Je pense que c'est une excellente idée, car le "voici les résultats / il n'y a pas de résultats" est un idiome assez courant dans les applications Web.Pourquoi ne pas mélanger quelques réponses en une seule?
Une syntaxe de construction de contrôle de flux généralisée et extensible dans un langage impératif serait plutôt utile et divertissante. Jusqu'à ce que cela apparaisse, je suppose que je vais simplement utiliser Lisp ou quelque chose.
la source
seventh { ... }
.Les structures de contrôle en tant que fonctions.
Je veux
for
,if
,else
,while
, etc. comme des fonctions, et non pas des structures spéciales.Je veux
return
,try/except
etgoto
être des dérivés de suites.Bien sûr, cela a moins à voir avec une structure de contrôle particulière et plus à voir avec la façon dont vous voyez les structures de contrôle en général, la méta des structures de contrôle.
la source
for
,if
,else
etwhile
que les fonctions me fait déduis que les paramètres de ces fonctions doivent être exécutées paresseusement afin de se comporter les mêmes que les constructions d' origine. Avoir la capacité de faire une exécution paresseuse serait bien.return
, les exceptions, etc. Mais maintenant, le programmeur expert a un outil supplémentaire puissant dans sa boîte à outils si le besoin s'en fait sentir. En outre, les langues à mon humble avis ne devraient pas être "abruties". Les langues devraient avoir la capacité de soutenir une expertise accrue et la croissance des connaissances en matière de CS.L'article lié comprend clairement les boucles N + 1/2 de Donald Knuth . Exprimé en C / C ++ / Java:
Ceci est utile pour lire des lignes ou des caractères d'un fichier, tester si vous avez atteint EOF, puis le traiter. Je suis tellement habitué à voir le motif
for(;;)..if(..)break;
apparaître qu'il est idiomatique pour moi. (Avant d'avoir lu l'article de Knuth, réimprimé dans le livre Literate Programming , celui-ci était un "wtf?".)Knuth a suggéré les mots clés
loop/while/repeat
:Où
S
etT
sont les espaces réservés pour une série de zéro ou plusieurs instructions, etC
est une condition booléenne. S'il n'y avait pas deS
déclaration, ce serait une boucle while, et s'il n'y avait pas deT
déclaration, ce serait une boucle do.Cette construction elle-même pourrait être généralisée en autorisant zéro ou plusieurs
while C
clauses, ce qui la rend parfaite pour exprimer des boucles infinies, puis des conditions plus rares qui nécessiteraient deux vérifications.Dans le même article, Knuth a suggéré un mécanisme de signalisation qui serait une version locale des exceptions de lancement / capture (comme alternative à l'utilisation de goto).
Pour moi? Je souhaite que Java supporte l'optimisation des appels, afin que je puisse exprimer n'importe quelle structure de contrôle générale selon les besoins.
Mise à jour: j'ai oublié de mentionner que de nombreux programmeurs C / C ++ / Java contournent celui-ci en utilisant une affectation intégrée dans l'état de
while
:En utilisant les termes de la construction de Knuth, cela est permis quand
S
etC
peut être combiné en une seule expression. Certaines personnes détestent voir l'affectation intégrée ci-dessus, tandis que d'autres détestent voirbreak
ce quifor (;;)
précède. Mais quandS
etC
ne peut pas être combiné, comme quandS
a plusieurs instructions, lefor (;;)
est la seule alternative sans répéter le code. L'autre alternative est de simplement dupliquer leS
code:L'
loop/while/repeat
alternative de Knuth semble bien meilleure.la source
repeat-until
boucle Pascal .do while ... loop until
- à la fois la précondition et la postcondition sont facultatives, et je me souviens (vaguement) d'avoir utilisé les deux dans une boucle. Pour votre condition moyenne, il y a l'Adaexit when ...;
. Le principal avantageif ... break;
est que vous pouvez écrireexit loopname when ...;
pour quitter simultanément plusieurs boucles imbriquées (mais pas nécessairement toutes). Probablement légèrement plus visible que cette cassure aussi.Le langage BCPL avait une
valueof
expression qui pouvait être utilisée pour transformer une séquence d'instructions en une seule expression:Où
some series of statements
peut être n'importe quoi et le toutvalueof
s'évaluev
.Cela peut être utile en Java lorsque vous devez calculer un argument pour appeler un
this()
ousuper()
(ce qui nécessite que rien ne se passe avant). Bien sûr, vous pouvez simplement écrire une méthode distincte, mais cela pourrait être difficile si vous devez passer de nombreuses valeurs locales pour le contexte.Si vous pouvez utiliser
final
pour les variables nécessaires, vous pouvez déjà faire unvalueof
en Java en utilisant des classes internes anonymes:la source
({ statement1; statement2; ...; result-expr; })
. J'ai vu pareil ailleurs aussi, mais je ne me souviens pas où. Probablement tous copiés depuis BCPL.fait la même chose que:
fait la même chose que:
la source
unless
.Sur une note différente, je voudrais voir un meilleur support pour les itérateurs dans les langages de programmation. En particulier, lorsque vous souhaitez descendre deux collections par paires :
Certains langages dynamiques peuvent déjà l'avoir, ou être facilement pris en charge via des bibliothèques et des macros, mais je pense que c'est dans l'esprit de votre question.
Si les deux ensembles ne sont pas de la même taille, cela pourrait déclencher une exception ou vous pourriez avoir un
else
après la boucle pour signaler qu'il y avait une différence de taille.Naturellement, vous pouvez généraliser cela pour descendre trois listes ou plus.
Mise à jour: Il serait également utile de faire le produit cartésien entre les itérables:
qui ne serait rien de plus que des boucles imbriquées:
Je m'inquiète un peu qu'entre les deux notations que j'ai fournies ici, il y ait une différence O (n) et O (n ^ 2) dans le nombre de paires, avec seulement le changement d'un seul caractère.
la source
for a, b, c in itertools.product(iter1, iter2, iter3):
vous donne le produit cartésien évalué paresseusement. Qu'est-ce que c'est? Vous voulez aussi des permutations et des combinaisons d'un itérateur donné?itertools.permutations
,itertools.combinations
.Il existe ce qu'on appelle la "boucle de Dijkstra" (également appelée "boucle gardée de Dijkstra"). Il a été défini dans The Guarded Command Language (GCL) . Vous pouvez trouver des informations sur la syntaxe et la sémantique dans l'article Wikipédia ci-dessus à la section 6 Répétition: faire .
De nos jours, je connais en fait un langage de programmation qui prend directement en charge cette structure de contrôle. Il s'agit d' Oberon-07 (PDF, 70 Ko). Et il prend en charge "Dijkstra's Loop" sous votre forme de déclaration while. Jetez un œil à la section 9.6. Alors que les déclarations dans le PDF ci-dessus.
PS Ceci est une copie de ma réponse SO .
la source
Expressions de style icône avec retour en arrière intégré.
Python bénéficie de nombreux avantages du générateur d'icônes - et en fait un meilleur travail en général, l'OMI. Et en principe, le retour en arrière n'était qu'une sorte de lancer d'exception, mais c'était la simplicité des expressions l'équivalent approximatif de ...
pour gérer les cas d'échec comme la division par zéro.
Où Icon est devenu fou - aucun opérateur de comparaison à retour booléen. Les comparaisons ont toujours réussi ou déclenché un retour en arrière, et il y avait un autre problème sémantique dont j'essaie désespérément de me souvenir ... eh bien, disons simplement qu'il est probablement plus réprimé qu'oublié.
J'ai toujours pensé qu'ils devraient avoir une
if
expression sans autre partie -if (condition, success-value)
genre de chose, revenir en arrière si la condition retourne fausse - et abandonner les comparaisons étranges.EDIT Je me souviens - vraiment évident. Une comparaison avec deux arguments réussit ou échoue - elle ne calcule pas de nouvelle valeur à renvoyer. Alors, quand il réussit, que revient- il? Réponse - l'un des arguments. Mais si vous écrivez
a > b
, quel est l'argument logique pour retourner -a
oub
? Et si vous écrivez à lab < a
place? Je pense que cela renvoyait toujours le bon argument, ce qui a autant de sens que n'importe quoi, mais cela me semblait toujours le mauvais argument.la source
Ce n'est qu'une idée générale et une syntaxe:
La condition AUSSI est toujours évaluée. ELSE fonctionne comme d'habitude.
Cela fonctionne pour le cas aussi. C'est probablement un bon moyen d'éliminer la déclaration de rupture:
peut être lu comme:
Je ne sais pas si c'est utile ou simple à lire mais c'est un exemple.
la source
La continuité du style de passage me vient à l'esprit. Ensuite, bien sûr, vous aimeriez également avoir l' optimisation des appels de queue .
la source
goto return ...;
déclaration, rendant l'intention d'appeler la queue explicite, donc si le compilateur ne peut pas le rendre itératif, c'est une erreur.Branche de thread transparente, elle a la syntaxe comme une fonction, mais s'exécute dans un thread séparé et ne peut pas accéder aux données qui ne lui ont pas été initialement transmises.
Lorsqu'une branche est appelée, elle renvoie immédiatement un handle.
La poignée peut être utilisée pour vérifier si la tâche est terminée.
Si le résultat est demandé avant la fin de l'exécution, le thread principal attendra simplement.
Cela ne couvrirait pas les scénarios de multithreading les plus avancés, mais fournirait plutôt un moyen facilement accessible de commencer à utiliser plusieurs cœurs.
la source
handle.finished()
test, maisspawn
etsync
c'est tout ce dont vous avez besoin pour 90% des tâches de programmation parallèle.Les blocs FIRST et THEN s'exécutent si l'une des 3 conditions est évaluée comme vraie. PREMIER bloc s'exécute avant le bloc conditionnel et ALORS s'exécute après l'exécution du bloc conditionnel.
ELSE l'écriture conditionnelle ou finale suivant les instructions FIRST et THEN est indépendante de ces blocs.
Il peut se lire comme suit:
Ces fonctions ne sont qu'un formulaire à lire. Ils ne créeraient pas de portée. Cela ressemble plus à un gosub / return de Basic.
Utilité et lisibilité comme sujet de discussion.
la source
Je me retrouve parfois à écrire une boucle qui doit faire quelque chose de différent lors de la première itération. Par exemple, afficher les balises <th> au lieu des balises <td>.
Je gère cette situation avec un drapeau booléen. Quelque chose comme ça:
Il semble stupide de vérifier la valeur de
first
à chaque itération alors que ce sera faux la plupart du temps.J'aimerais avoir une option de bouclage pour spécifier un corps de boucle différent lors de la première itération. Il n'y aurait pas besoin d'une variable distincte. Le code compilé n'en aurait pas besoin non plus, car le code généré aurait deux corps, un pour la première itération et un pour le reste.
la source
print(out, first "<th>" then "<td>")
if (!first) gimme-a-comma ();
, mais à peu près la même chose. Une objection que j'aurais, cependant - si vous le concluez correctement, vous vous retrouvez avec des choses comme la méthode de jointure de chaîne Python - quelle que soit la fréquence à laquelle vous avez besoin du modèle de base, la boucle sous-jacente n'a pas besoin d'être réécrite aussi souvent.if (!first)
, mais les micro-optimiseurs peuvent soulever des objections de prédiction de branche.if (!first)
et laisser un compilateur d'optimisation décider si le corps de la boucle est suffisamment petit pour que le déroulement et la suppressionfirst
soient une victoire nette.[copié de ma propre réponse sur stackoverflow]
ignoring
- Pour ignorer les exceptions se produisant dans un certain bloc de code.Avec une construction de contrôle ignorant, vous pouvez l'écrire de manière plus concise et plus lisible sous la forme:
[Scala fournit cela (et de nombreuses autres constructions de contrôle de gestion des exceptions) dans sa bibliothèque standard, dans le package util.control. ]
la source
try..catch
bloc vide est une chose; cela vous oblige à reconnaître l'erreur et à l'ignorer délibérément; tout en jetant des morceaux de code sous un ignorer global peut entraîner des problèmes lorsque ces exceptions sont levées, ainsi que de mauvaises habitudes de programmation.try
bloc, sauf qu'il répertorie les exceptions qu'il intercepte et ignore à l'avant, au lieu de plus tard. Cela pourrait même être un avantage de lisibilité - par exemple, faire savoir au lecteur qu'un fichier manquant n'est pas une erreur avant même de lire l'appel ouvert.Au lieu de:
Faites-le en Python, ou maintenant aussi en C #:
Scala a beaucoup de nouvelles fonctionnalités.
Enfin, des langages tels que Clojure peuvent être étendus pour fournir des fonctionnalités supplémentaires.
la source
J'ai deux idées.
Souvent, je trouve que je me répète par
catch
blocs. Cela peut être quelque peu aidé par l'extraction de méthodes, mais cela peut entraîner un encombrement inutile si les méthodes sont très courtes ou autrement dignes d'une méthode. Donc, ce serait bien d'imbriquer descatch
blocs:Dans la programmation Web, je me retrouve souvent à faire quelque chose comme ça (ce n'est pas un vrai exemple, alors n'analysez pas les cas fictifs):
En Javascript (enfin, ECMAScript, et peut-être d'autres que je ne connais pas), car n'importe quelle valeur peut être évaluée comme condition,
||
peut aider.J'aime vraiment à quoi cela ressemble, et je souhaite que plus de langues, en particulier certaines côté serveur, soient prises en charge. (PHP peut évaluer n'importe quoi en tant que condition, mais convertit toute l'expression conditionnelle en un booléen au lieu de conserver la valeur. Je ne sais pas pour Python ou Ruby.) Cela pourrait devenir compliqué après environ trois cas, mais si vous en avez plus de trois cas, vous pourriez également avoir une mauvaise conception de logiciel.
la source
x if c else y
syntaxe, une raison majeure qui est arrivé était parce que beaucoup d'expressions utilisant cette sémantique pour||
et&&
était bogué subtilement. IIRC un cas commun était une valeur (telle que zéro) qui était valide pour l'application en cours de traitementfalse
, étant ainsi rejetée de sorte qu'une solution de remplacement non valide était utilisée à la place. Cependant - voir ma réponse WRT le langage de programmation Icon, qui peut avoir des expressions commeget1() else get2() else default
.Le commutateur généralisé a dit ci-dessus:
À Haskell:
la source
En C #, je voudrais utiliser des
switch () { ... }
expressions simples mais extensibles:Etc. La même chose avec des chiffres ou d' autres types (que supports
IComparable
,IConvertible
...)Cela pourrait rendre mon code plus laconique et lisible.
la source
C'est une question amusante, comme l'a dit @Macneil.
Ma structure de contrôle inhabituelle préférée, que j'ai (humble toux) découverte, est l' exécution différentielle .
Il a certaines utilisations. Pour moi, l'écrasante utilisation est dans la programmation des interfaces utilisateur, ce qui est un exemple du problème plus général de la maintenance des données redondantes en correspondance. D'une part, il y a des données d'application, et d'autre part, il y a des contrôles d'interface utilisateur, qui doivent être maintenus en accord. Cela ressemble à "contraignant" mais il y a en fait beaucoup plus.
Habituellement, je l'implémente par des macros en C ou C ++. En C #, je dois le faire en développant des instructions à la main. C'est une douleur, mais ça marche.
Une fois que je l'ai implémenté en termes de macros Lisp, puis c'était très propre. Cela n'a pas exigé de prudence de la part du programmeur. J'aurais pu faire la même chose dans n'importe quel autre langage structuré si j'avais pris la peine d'écrire un analyseur complet puis de générer toutes les bonnes choses. C'est un gros projet et je ne l'ai pas fait.
la source
Les structures de contrôle "traditionnelles" comme le
for
contrôle du travailleur, le gardant soumis aux idéologies corrompues de l'élite capitaliste au pouvoir. C'est pourquoi j'utilise des structures de contrôle alternatives comme à laph0r
place. C'est commefor
, mais plus radical: vous ne vous surprendrez pas àph0r
porter un costume et une cravate, jaillissant de certains BS d'entreprise.ph0r
le garde réel, mec.Combattre le pouvoir!
la source
Simplest
for
boucle-la source