, , , ,

array

Le type array fournit un tableau de valeurs immuables. La structure du type array est immuable. On lui donne une taille fixe qui ne peut être modifiée qu'en créant un nouveau tableau et en y recopiant les élément du tableau précédent. Le type array est donc également conteneur dépourvu d'effet de bord. Son utilisation est donc particulièrement indiquée dans un environnement concurrent, où il s'utilise à l'aide de la stratégie «copy-on-write».

Un array n'est pas une liste. On accède donc facilement et rapidement (en temps constant ) aux éléments qu'il contient à l'aide d'un indice. Cependant, il est important de retenir que l'on ne peut que lire les éléments d'un array. Si on souhaite utiliser un tableau dont le contenu est mutable, il faut se tourner vers le type vector.


Créer un array

Le plus simple consiste à utiliser l'opérateur array pour construire un nouvel array par conversion d'un tuple, par exemple.

(define 'a (array[1 2 3]))
(display a)

(array[1 2 3])

Bien sûr, il est possible aussi de créer un nouvel array à partir de tous types qui implémente l'opérateur générique array.


Accéder aux éléments d'un array

Comme on l'a déjà dit plus haut, on accède aux élément d'un tableau par indice.

(define 'a (array["a" "b" "c" "d" "e" "f"]))
(display (a 2))

c

Le premier élément d'un tableau est accessible à l'indice 0. Et si le tableau à une taille de n éléments, le dernier est accessible à l'indice n-1.

Comme dans le cas des listes, le premier élément d'un tableau peut aussi être atteint à l'aide de l'opérateur car. Mais, cette possibilité présente moins d'intérêt que dans le cas des listes. Elle est toutefois disponible pour permettre la rédaction de programmes plus fortement génériques.


Ajouter des éléments

Pour ajouter des éléments dans un array, il suffit d'utiliser l'opérateur +.

(define '$a (array["a" "b" "c"]))
(set! $a (+ $a "d" "e" "f"))
(display $a)

(array["a" "b" "c" "d" "e" "f"])

Comme c'est aussi le cas pour les autres collections immuables, il est préférable d'ajouter plusieurs éléments d'un seul coup dans une seule opération que de les ajouter un par un. Cela évite la nécessité de dupliquer le tableau à chaque fois.

Comme cela a été rappelé plus haut, les array imposent la stratégie «copy-on-write» pour chaque modification. Il est donc inutile de synchroniser un array lorsqu'on le modifie dans un contexte concurrent. Il suffit tout simplement de l'affecter dans une section atomique à l'aide de l'opérateur atomic. De cette manière, on évite d'utiliser des verrous qui ralentissent ou bloquent l'exécution des processus concurrents. atomic permet de s'assurer de l'atomicité de la modification que nous apportons.

(define '$a (array[1 2 3]))
 
(atomic $a {set! $a (+ $a 4 5 6)})
 
(display $a)

(array[1 2 3 4 5 6])

Dans l'exemple ci-dessus, on a la garantie que l'ajout des éléments supplémentaires dans l'array $a est réalisé d'une manière atomique sans nécessiter de synchronisation par verrou1).


Concaténation et autres opérations

Pour concaténer plusieurs array, il suffit d'utiliser l'opérateur concat. Comme dans le cas, de +, il est préférable de concaténer plusieurs array d'un seul coup que d'ajouter un array à la fois. De même, si on affecte l'array résultant à une variable mutable, il est judicieux d'utiliser atomic pour s'assurer de l'atomicité de l'opération dans un contexte concurrent (si ce n'est pas le cas, atomic n'est pas nécessaire).

(display (concat (array[1 2 3]) (array["a" "b" "c"])))

(array[1 2 3 "a" "b" "c"])

On peut aussi obtenir une section d'un tableau. Bien entendu dans ce cas, la partie nécessaire est copiée pour fournir un nouveau tableau. Comme dans le cas des autres collections,les opérateurs supportés sont cdr, tail, head et slide.

Pour connaître la taille d'un tableau, il suffit d'utiliser length. De même que pour les autres collection, le type array fournit aussi une valeur de vérité: (false) lorsque l'array est vide.


Opérateurs


1)
Sans atomic, si 2 processus tentaient d'affecter $a, il est possible que l'un écrase les modification de l'autre. atomic s'assure que chaque processus affecte la variable avec une publication respective correcte.