.. meta:: :description lang=fr: List.iteri et Array.iteri en OCaml :description lang=en: List.iteri and Array.iteri in OCaml #################################### List.iteri et Array.iteri en OCaml #################################### .. note:: Un petit article sur deux fonctions pratiques `du langage OCaml `_. .. warning:: Si le mot OCaml n'évoque rien pour vous, cet article ne vous intéressera pas ! ``List.iter`` et ``Array.iter`` ------------------------------- Ces deux fonctions sont des classiques des modules *List* [#listiter]_ et *Array* [#arrayiter]_. Ces fonctions sont des itérateurs du type suivant : .. code-block:: ocaml val List.iter : ('a -> unit) -> 'a list -> unit val Array.iter : ('a -> unit) -> 'a array -> unit Elles permettent donc d'appliquer une fonction *f : 'a -> unit* qui agit par effets de bords (e.g., affichage) à **chaque élément** d'une liste (ou d'un tableau). Pratique donc ! Une meilleure version ? ----------------------- *Mais*… Souvent, on a besoin, en plus de la valeur ``x`` de chaque élément, de leur **indice** ``i`` (par exemple pour afficher "la case i contient x[i]" ou autre). Donc, on aimerait aussi avoir des itérateurs du type suivant : .. code-block:: ocaml val List.iteri : (int -> 'a -> unit) -> 'a list -> unit val Array.iteri : (int -> 'a -> unit) -> 'a array -> unit Où désormais *f* prend en premier argument **l'indice correspondant à son deuxième argument**. Très pratique pour éviter les boucles *for* ! .. note:: En Python… ? La syntaxe commune à tous les *itérateurs* permet d'éviter ça de toutes façons, e.g. : .. code-block:: python for i in [2*i for i in range(8)]: print i Et la fonction `enumerate `_ permet de faire ça aussi, en itérant sur ``i, xi``. Deux fonctions qui ont tardées à venir -------------------------------------- On constate que si *Array.iteri* a été codée en 1997 [#arraydiff]_, son équivalent pour les listes *List.iteri* n'a été ajoutée **qu'en… 2010** avec OCaml v4.00.1 ! (cf [#listdiff]_). Quel est le problème ? ---------------------- Ces fonctions sont assez pratiques, donc souvent utilisés. Dans le cadre des projets et autre exercices demandés par certains cours à l'`ENS Cachan `_, il faut faire marcher son code sur (au moins) une machine de la *salle 411*, qui sont **vieilles** ! C'est ainsi qu'en décembre 2013, nous avions perdu quelques minutes (durant un examen oral !) à trouver la source du problème, et inclure un petit *"patch"* v3.12 → v4.01.0 en ajoutant *à la main* le code de *List.iteri* dans nos projets [#projet]_. En particulier, ce lien [#patch]_ montre les modifications effectuées sur mon code lors de la découverte de ce bug. Bref, on aurait aimé les avoir plus tôt ! ----------------------------------------- Voilà un titre qui résume bien le message (inutile) de ce petit post. ------------------------------------------------------------------------------ .. rubric:: Références .. [#arrayiter] :Documentation: `Array.iter `_ dans la doc du module Array; .. [#listiter] :Documentation: `List.iter `_ dans la doc du module List; .. [#arraydiff] :Source: le `diff pour array.ml `_ qui a introduit *Array.iteri* (sur le *svn* de l'INRIA); .. [#listdiff] :Source: le `diff pour list.ml `_ qui a introduit *List.iteri* (sur le *svn* de l'INRIA); .. [#projet] :Voir: le `rapport `_ du projet **Laby** fait en décembre 2013 pour l'épreuve de modélisation de l'agrég; .. [#patch] :Voir: le `commit `_ rapportant la compatibilité avec OCaml v3.12.1 pour mon projet **Laby** (privé). ------------------------------------------------------------------------------ .. note:: *« Mais OCaml c'est nul non ? »* **Non**, faut pas écouter `ceux qui disent ça `_, OCaml c'est super ! .. (c) Lilian Besson, 2016, https://bitbucket.org/lbesson/web-sphinx/