2 votes

Surcharge d'une commande Tcl standard

Petite requête relative à la portée de la procédure

proc lappend {args} {
   set a $args
   lappend a testing ;# souhaite appeler la commande lappend Tcl intégrée
   puts "$a"
}

set list {new to tcl}
lappend $list

13voto

Donal Fellows Points 56559

Si vous faites simplement cela, cela ne fonctionnera pas. Il remplacera le lappend standard et vous obtiendrez une récursion infinie (enfin, vous aurez une vérification de la profondeur de la pile). Il existe plusieurs façons de contourner cela.

Mettre votre code dans un espace de noms

Si votre code est dans un espace de noms, il résoudra d'abord le lappend dans cet espace de noms, et n'utilisera le namespace global que si cette recherche locale échoue. Vous pouvez l'utiliser comme ceci :

namespace eval myNS {
    proc lappend {args} {
        set a $args
        ::lappend a testing ;# Forcer l'utilisation de la commande lappend globale
        puts "$a"
    }

    set list {new to tcl}
    lappend $list
}

Il existe des variations possibles, namespace eval myNS {source example.tcl} (avec votre code étant presque verbatim dans ce fichier sourcé) étant l'une des plus intéressantes car elle permet au code d'être principalement agnostique au namespace.

Renommer la commande globale lappend

Vous pouvez également déplacer la commande standard de cette manière :

rename lappend lappend_original
proc lappend {args} {
   set a $args
   lappend_original a testing
   puts "$a"
}

set list {new to tcl}
lappend $list

Cette technique fonctionne très bien, tant que vous n'avez pas trop de code se disputant qui a réellement la commande originale. Elle a été utilisée par de nombreux scripts Tcl au fil des ans.

Solution au problème réel : suivi de l'exécution

Bien sûr, la commande lappend n'est pas une que vous voulez vraiment remplacer car elle est largement utilisée dans de nombreux codes de bibliothèque Tcl. Pour le problème de savoir où un morceau de code appelle réellement lappend et quels arguments sont passés, il est bien meilleur d'utiliser une trace d'exécution. (Le lien renvoie à la documentation Tcl 8.6, mais cette API est en place depuis Tcl 8.4 donc vous devriez l'avoir disponible.)

proc runningLappend {cmdAndArgs operation} {
    puts [lrange $cmdAndArgs 1 end]
}
trace add execution lappend enter runningLappend

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X