next up previous contents index
Next: Gestion de la mémoire Up: Premiers pas éclairés... Previous: Introduction   Contents   Index

Subsections


Les objets composés

Scheme possède deux types d'objets structurés : la paire qui permet de construire des listes et le vecteur.


La paire

La paire rassemble deux objets Scheme entre eux. La fonction cons permet de construire une paire.

Une paire est affichée entre parenthèses. Si le second élément n'est pas une paire, il est séparé du premier par un point. Si le second élément est une paire, il est séparé du premier par un espace, et les parenthèses qui l'auraient entouré sont supprimées :

Osm> (cons 1 2) 
  => (1 . 2)

Osm> (cons 1 (cons 2 3))
  => (1 2 . 3)

Osm> (cons (cons 1 2) (cons 3 4))
  => ((1 . 2) 3 . 4)

La fonction5.1 car retourne le premier élément d'une paire et la fonction cdr5.2 retourne le second élément :

Osm> (car (cons 1 2)) 
  => 1

Osm> (cdr (cons 1 2)) 
  => 2

Le prédicat pair? retourne #t (true = vrai) si son argument est une paire et #f (false = faux) sinon :

Osm> (pair? (cons 1 2)) 
  => #t

Osm> (pair? 1)
  => #f

Il est possible de construire et de manipuler des structures plus complexes à l'aide de ces fonctions élémentaires :

Osm> (define (construit-client nom prénom age)
       (cons nom (cons prénom age)))
  => #unspecified

Osm> (define (nom-de client)
       (car client))
  => #unspecified

Osm> (define (prénom-de client)
       (car (cdr client)))
  => #unspecified

Osm> (define (age-de client)
       (cdr (cdr client)))
  => #unspecified

Osm> (define durand (construit-client 
                     "Durand"
                     "Yves"
                     26))
  => #unspecified

Osm> durand
  => ("Durand" "Yves" . 26)

Osm> (nom-de durand)
  => "Durand"

Osm> (prénom-de durand)
  => "Yves"

Osm> (age-de durand)
  => 26

Voilà de quoi construire des structures de données complexes.

Il existe aussi deux fonctions utiles set-car! et set-cdr! permettant de modifier respectivement le premier et le second élément d'une paire :

Osm> (define une-paire (cons 1 2))
  => #unspecified

Osm> une-paire
  => (1 . 2)

Osm> (set-car! une-paire 256)
  => #unspecified

Osm> une-paire
  => (256 . 2)

Par convention, les fonctions dont le nom se termine par un point d'exclamation ne sont pas fonctionnelles. C'est à dire qu'elles ont un effet de bord et qu'elles modifient l'état du système. En général, elles retournent #unspecified. De même, par convention, les fonctions dont le nom se termine par un point d'interrogation retournent un booléen.


La liste

Les paires sont aussi utilisées pour construire les listes. Une liste est une paire dont tous les seconds éléments sont des paires et dont le dernier second élément est la paire vide.

Par convention, la paire vide s'écrit '(). Ecrivons :

Osm> '()
  => '()

Osm> (cons 1 '())
  => (1)

Osm> (cons 1 (cons 2 '()))
  => (1 2)

Pour construire aisément des listes, Scheme définit aussi la fonction list :

Osm> (list 1 2 3 4)
  => (1 2 3 4)

Pour accéder au nième élément d'une liste, nous avons la fonction list-ref qui prend comme argument une liste et un index :

Osm> (list-ref (list 1 2 3 4) 0) 
  => 1

Osm> (list-ref (list 1 2 3 4) 3)
  => 4

Osm> (list-ref (list 1 2 3 4) 4)
  => Error : index 4 is invalid

De la même manière, pour modifier le nième élément d'une liste, nous avons la fonction list-set! qui prend comme argument une liste, un index et la valeur :

Osm> (define une-liste (list 1 2 3 4)) 
  => #unspecified

Osm> une-liste
  => (1 2 3 4)

Osm> (list-set! une-liste 0 256)
  => #unspecified

Osm> une-liste
  => (256 2 3 4)

Pour savoir si un objet est une liste, nous avons le prédicat list? :

Osm> (list? une-liste) 
  => #t

Osm> (list? (cons 1 (cons 2 3)))
  => #f

Pour savoir si un objet est la paire vide, Scheme définit null? :

Osm> (null? '())
  => #t

On remarque que le prédicat pair? retourne faux s'il est appliqué à la paire vide '().

Il faut noter que les fonctions list-ref et list-set! parcourent à chaque fois les n premiers éléments de la liste et la fonction list? parcourt la totalité de la liste, ce qui peut être très inefficace dans certains cas. Pour améliorer les performances sur des structures de données complexes, Scheme définit les vecteurs.


Le vecteur

Un vecteur permet de regrouper dans une même structure plusieurs objets Scheme. Pour construire un vecteur en connaissant ses composantes, on utilise la fonction vector :

Osm> (vector 1 2 3 4) 
  => #(1 2 3 4)

Le vecteur est affiché comme une liste préfixée par un dièse. Lorsque l'on veut construire un vecteur en connaissant seulement le nombre de ses éléments, et éventuellement la valeur initiale de ses composantes, on utilise make-vector :

Osm> (make-vector 3) 
  => #(#unbounded #unbounded #unbounded)

Osm> (make-vector 3 123)
  => #(123 123 123)

On remarque que cette fonction accepte un nombre d'arguments variable. Il est possible d'écrire un vecteur directement, comme dans :

Osm> #(1 2 3)
  => #(1 2 3)

la fonction vector-ref permet d'accéder à la nième composante d'un vecteur :

Osm> (vector-ref (vector 1 2 3) 0) 
  => 1

Osm> (vector-ref (vector 1 2 3) 2)
  => 3

Osm> (vector-ref (vector 1 2 3) 3)
  => Error : index 3 is invalid

Pour modifier la nième composante, il existe la fonction vector-set! :

Osm> (define un-vecteur (vector 1 2 3 4)) 
  => #unspecified

Osm> un-vecteur
  => #(1 2 3 4)

Osm> (vector-set! un-vecteur 0 256)
  => #unspecified

Osm> un-vecteur
  => #(256 2 3 4)

Enfin, Scheme définit la fonction vector? comme prédicat.

Contrairement aux fonctions relatives aux listes, les fonctions concernant les vecteurs ne parcourent pas les éléments du vecteur pour effectuer leur traitement. Elles procèdent à des accès directs, ce qui les rend très efficaces.

Reprenons notre exemple client avec les vecteurs :

Osm> (define (construit-client nom prénom age)
       (vector nom prénom age))
  => #unspecified

Osm> (define (nom-de client)
        (vector-ref client 0))
  => #unspecified

Osm> (define (prénom-de client)
        (vector-ref client 1))
  => #unspecified

Osm> (define (age-de client)
        (vector-ref client 2))
  => #unspecified

Osm> (define durand (construit-client 
                     "Durand"
                     "Yves"
                     26))
  => #unspecified

Osm> durand
  => #("Durand" "Yves" 26)


next up previous contents index
Next: Gestion de la mémoire Up: Premiers pas éclairés... Previous: Introduction   Contents   Index
© 1993 to 2001 Erian Concept