2 votes

Utilisation de la commande TCL eval avec "set"

Voici le code que je teste :

proc check_eval {} {
    set cmd {set return_val {}; set return_val}
    puts "Command to evaluate : $cmd"
    uplevel eval $cmd
}

J'ai rencontré le problème suivant : lorsque j'appelle "check_eval", il semble que l'instruction "set return_val {}" soit ignorée. En d'autres termes, l'interpètre recherche la variable return_val existante dans le champ d'application de l'appel. Exemple :

tcl>unset return_val
tcl>check_eval
Command to evaluate : set return_val {}; set return_val
can't read "return_val": no such variable
while evaluating check_eval

tcl>set return_val 556
556
tcl>check_eval
Command to evaluate : set return_val {}; set return_val
556
tcl>

En revanche, si je remplace "set return_val {}" dans la procédure par, par exemple, "set return_val 10000", elle affichera 10000 lors de son exécution :

tcl>set return_val 556
556
tcl>check_eval
Command to evaluate : set return_val 10000; set return_val
10000
tcl>set return_val
10000

Quelqu'un peut-il m'expliquer ce qui se passe ici ?

Gracias.

4voto

potrzebie Points 1064

Vous effectuez deux niveaux d'évaluation/interprétation, d'abord avec la uplevel puis avec eval et l'accolade qui entoure le cmd script ne vous protège que de la première.

Vous n'avez pas besoin eval Cela suffira :

uplevel $cmd

EDIT : Les deux eval y uplevel concat :enate all their arguments together into a flat string and evaluate it comme un script. (avec uplevel vous pouvez choisir un autre cadre de pile pour l'exécuter). Ils n'utilisent pas le premier argument en tant que commande unique et le reste des arguments comme arguments à envoyer à cette commande. Si c'était le cas, vous obtiendriez un message d'erreur de la part de votre eval que la commande "set return_val {} ; set return_val" n'a pas été trouvée. Vous utilisez donc eval correctement mais uplevel erronée.

uplevel exécute ce script...

eval set return_val {}; set return_val

...qui est cassé à plus d'un titre, parce que vous n'avez pas cité (regroupé) ses arguments.

eval n'est pas nécessaire dans votre exemple, mais si vous avez besoin d'appeler une seule commande à un niveau supérieur, sans que ses arguments soient concaténés, la façon de citer des chaînes statiques lorsque vous n'avez pas besoin de substitutions, est d'utiliser des accolades :

uplevel {after 1000 {set return_val {}; set return_val}}

...et la façon de citer des chaînes dynamiques avec des valeurs substituées est avec list :

set cmd {set return_val {}; set return_val}
uplevel [list after 1000 $cmd]

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