Imaginez que vous êtes le chef de cuisine d'un restaurant et que vous êtes tous en train de préparer une énorme omelette pour un buffet. Vous remettez un carton contenant une douzaine d'œufs à chacun des deux membres du personnel de cuisine et leur dites de se mettre au travail, littéralement.
Le premier installe un bol, ouvre la caisse, saisit chaque œuf à tour de rôle - de gauche à droite à travers la rangée supérieure, puis la rangée inférieure - en le cassant contre le côté du bol, puis en le vidant dans le bol. Il finit par ne plus avoir d'œufs. Un travail bien fait.
Le second installe un bol, ouvre la caisse et s'empresse d'aller chercher une feuille de papier et un stylo. Il écrit les chiffres 0 à 11 à côté des compartiments de la boîte à œufs, et le chiffre 0 sur le papier. Il regarde le nombre sur le papier, trouve le compartiment marqué 0, prend l'œuf et le casse dans le bol. Il regarde à nouveau le 0 sur le papier, pense "0 + 1 = 1", raye le 0 et écrit 1 sur le papier. Il prend l'œuf dans le compartiment 1 et le casse. Et ainsi de suite, jusqu'à ce que le chiffre 12 soit sur le papier et qu'il sache (sans regarder !) qu'il n'y a plus d'œufs. Un travail bien fait.
On pourrait penser que le deuxième gars était un peu dérangé dans sa tête, non ?
L'intérêt de travailler dans un langage de haut niveau est d'éviter de devoir décrire les choses dans les termes de l'ordinateur et de pouvoir les décrire dans vos propres termes. Plus le langage est de haut niveau, plus cela est vrai. L'incrémentation d'un compteur dans une boucle est une distraction de ce que vous voulez vraiment faire : traiter chaque élément.
De plus, les structures de type liste chaînée ne peuvent pas être traitées efficacement en incrémentant un compteur et en indexant : "Indexer" signifie recommencer à compter depuis le début. En C, nous pouvons traiter une liste chaînée que nous avons créée nous-mêmes en utilisant un pointeur pour le "compteur" de la boucle et en le déréférençant. Nous pouvons faire cela dans le C++ moderne (et dans une certaine mesure dans le C# et le Java) en utilisant des "itérateurs", mais cela souffre toujours du problème de l'indirectité.
Enfin, certains langages sont d'un niveau suffisamment élevé pour que l'idée de réellement écrire une boucle pour "effectuer une opération sur chaque élément d'une liste" ou "rechercher un élément dans une liste" est consternant (de la même manière que le chef cuisinier ne devrait pas avoir à dire au premier membre du personnel de cuisine comment s'assurer que tous les œufs sont cassés). Des fonctions sont fournies pour mettre en place cette structure de boucle, et vous leur dites - via une fonction d'ordre supérieur, ou peut-être une valeur de comparaison, dans le cas d'une recherche - ce qu'il faut faire dans la boucle. (En fait, vous pouvez faire ces choses en C++, bien que les interfaces soient quelque peu maladroites).