Tcl par l'exemple - Une nouvelle commande ldelete

 

ulis, 2007-01-24.

Exercices : copiez-collez les exemples, exécutez-les puis modifiez-les. Durée : 30mn.


Pourquoi

Pour ajouter à Tcl la commande ldelete réciproque de lappend :


Comment

En utilisant les commandes


lreplace

Pour une description officielle de la commande voir lreplace.

La command lreplace prend trois groupes d'arguments :

  1. une liste (la valeur de la liste),
  2. deux indices (début et fin de la sous-liste à remplacer),
  3. une sous-liste d'éléments (qui peut être vide).

Elle retourne une nouvelle liste où la sous-liste à remplacer est remplacée par la sous-liste fournie dans les arguments.

Pour remplacer dans la liste suivante les éléments 3 et 4 par trois et quatre :

  set liste [list un deux 3 4 cinq]
  set liste [lreplace $liste 2 3 trois quatre]

La liste initiale {un deux 3 4 cinq} a été remplacée par {un deux trois quatre cinq} :

  1. la liste initiale : {un deux 3 4 cinq}
  2. les deux indices : 2 3 (indiquant la sous-liste {3 4})
  3. la sous-liste : trois quatre (qui remplace la sous-liste décrite au 2.)

Pour supprimer des élément on remplace la sous-liste décrite en 2. par une sous-liste vide :

  set liste [list 1 2 3 3a 3b 4}
  set liste [lreplace $liste 3 4]

Ici la sous-liste {3a 3b} (décrite par les indices 3 4) est remplacée par rien.

La liste résultante est {1 2 3 4}.


upvar

Pour une description officielle de la commande voir upvar.

La commande upvar permet d'accéder à une variable dans un contexte englobant.

Pour la notion de contexte voir contexte.

Ici elle va permettre de connaître, dans la procédure en cours d'exécution, la valeur de la liste définie lors de l'appel de la procédure :

  proc dump-list1 {lname} \
  {
    upvar 1 $lname _list
    puts $_list
  }
  set liste [list 1 2 3 4]
  dump-list1 liste

Attention : la procédure dump-list1 a reçu non pas la valeur de la liste mais le nom de la liste.

Voici, pour faire la différence, un script où la procédure reçoit la valeur de la liste :

  proc dump-list2 {liste} \
  {
    puts $liste
  }
  set liste [list 1 2 3 4]
  dump-list2 $liste

Dans ce deuxième exemple la procédure reçoit la valeur de la liste et peut donc l'imprimer.

Alors, quel est l'intérêt du premier exemple (qui est plus compliqué) ? De simplifier l'utilisation de la nouvelle commande.

  set liste [ldelete $liste 2]
   ldelete liste 2
   lappend liste $item

Pour en revenir au script avec upvar :

  proc dump-list1 {lname} \
  {
    upvar 1 $lname _list
    puts $_list
  }
  set liste [list 1 2 3 4]
  dump-list1 liste

La commande upvar, dans la forme utilisée ici, prend trois arguments :

  1. Le nombre de contextes à traverser pour atteindre le contexte source,
  2. le nom de la variable dans le contexte source,
  3. le nom de la variable dans le contexte local.

Un contexte est l'ensemble des variables référençables et procédures appelables simplement. Dans une procédure ce sont les variables locales et les procédures globales.

Le contexte de la procédure dump-list1 est au niveau 0. Avec upvar 1 on accède au niveau appelant (c'est celui de la commande ''dump-list1 liste').

Le nom de la variable dans le contexte source c'est liste. Ce nom est passé en argument à la procédure par :

  dump-list1 liste

Le nom de la variable dans le contexte local (de la procédure) c'est _list défini par :

  upvar 1 $lname _list

Dans la procédure dump-list1 la variable de nom _list permet d'accéder à la valeur de la variable liste du contexte appelant. C'est à dire à la valeur {1 2 3 4}.

(Mais si c'est simple : suffit de relire une deuxième fois)


catch

Pour une description officielle de la commande voir catch.

La commande catch prend deux arguments :

Elle retourne un code valant :

  set rc [catch { set a b } result]

Lors de l'exécution du script précédent, la variable rc reçoit 0 et la variable result reçoit "b" (valeur retournée par set a b).

  set rc [catch { set a b c } result]

Lors de l'exécution du script précédent, la variable rc reçoit 1 pour indiquer une erreur et la variable result reçoit le message d'erreur.


return

Pour une description officielle de la commande voir return.

La commande return peut prendre un argument et recevoir plusieurs options.

Ici c'est la forme return -code code result qui est utilisée.

L'option -code peut recevoir plusieurs valeurs :


ldelete

Description

La commande supprime un ou plusieurs éléments dans une liste.

syntaxe :

  ldelete lname start ?stop?

La commande retourne la liste modifiée.

script

  proc ldelete {lname start {stop ""}} \
  {
    upvar 1 $lname _list
    if {$stop == ""} { set stop $start }
    set rc [catch \
    {
      if {$start < 0} { set start 0 }
      if {$stop < $start} { set stop $start }
      set _list [lreplace $_list $start $stop]
    } result]
    return -code $rc $result
  }

exemple

  set liste [list zéro un deux trois quatre]
  ldelete liste 1 2

La nouvelle liste a pour valeur {zéro trois quatre} (les élément un et deux ont été supprimés).

Explications

La procédure ldelete prend 3 arguments dont le dernier est optionnel.

La commande upvar permet d'accéder (par le nom _list) à la valeur de la liste du contexte appelant dont le nom est dans la variable lname.

La commande lreplace supprime les éléments demandés et retourne la valeur de la nouvelle liste qui est mise dans la variable _list (c'est à dire dans la variable liste du contexte appelant).

La command catch permet de récupérer les erreurs générées par les expressions des commandes if ou par la commande lreplace.

La commande return renvoie le résultat :

Remarque : L'utilisation du couple de commandes catch/return permet de cacher le fait que la commande ldelete est implémentée par une procédure.


Voir Aussi


Discussion


Catégorie Exemple | Catégorie Tcl par l'exemple