tcl
Expressions
Recherche…
Remarques
Un autre avantage de l'utilisation de chaînes d'expression contreventées est que le compilateur d'octets peut généralement générer un code plus efficace (5 à 10 fois plus rapide).
Les problèmes avec les expressions sans entraves
Il est conseillé de fournir des arguments de type chaîne d'expression sous forme de chaînes de contours. La rubrique "Double substitution" souligne des raisons importantes derrière la même.
La commande expr évalue une chaîne d'expression basée sur un opérateur pour calculer une valeur. Cette chaîne est construite à partir des arguments de l'invocation.
expr 1 + 2 ; # three arguments
expr "1 + 2" ; # one argument
expr {1 + 2} ; # one argument
Ces trois invocations sont équivalentes et la chaîne d'expression est la même.
Les commandes if , for et while utilisent le même code évaluateur pour leurs arguments de condition:
if {$x > 0} ...
for ... {$x > 0} ... ...
while {$x > 0} ...
La principale différence est que la chaîne d'expression de condition doit toujours être un seul argument.
Comme pour tout argument d'une invocation de commande dans Tcl, le contenu peut ou non être soumis à une substitution, en fonction de la manière dont ils sont cités / échappés:
set a 1
set b 2
expr $a + $b ; # expression string is {1 + 2}
expr "$a + $b" ; # expression string is {1 + 2}
expr \$a + \$b ; # expression string is {$a + $b}
expr {$a + $b} ; # expression string is {$a + $b}
Il existe une différence dans les troisième et quatrième cas, car les barres obliques / accolades empêchent la substitution. Le résultat est toujours le même, puisque l'évaluateur dans expr peut lui-même effectuer la substitution de variables Tcl et transformer la chaîne en {1 + 2} .
set a 1
set b "+ 2"
expr $a $b ; # expression string is {1 + 2}
expr "$a $b" ; # expression string is {1 + 2}
expr {$a $b} ; # expression string is {$a $b}: FAIL!
Nous rencontrons ici des problèmes avec l'argument contre-courant: lorsque l'évaluateur expr des substitutions, la chaîne d'expression a déjà été analysée en opérateurs et opérandes. L'évaluateur voit donc une chaîne composée de deux opérandes sans opérateur entre elles. (Le message d'erreur est " missing operator at _@_ in expression "$a _@_$b" ".)
Dans ce cas, la substitution de variable avant appel à expr a empêché une erreur. Le renforcement de l'argument empêchait la substitution de variables jusqu'à l'évaluation de l'expression, ce qui entraînait une erreur.
De telles situations peuvent se produire, le plus souvent lorsqu'une expression à évaluer est transmise en tant que variable ou paramètre. Dans ces cas, il n’ya pas d’autre choix que de laisser l’argument sans contrainte pour permettre à l’évaluateur d’argument de «décompresser» la chaîne d’expression à expr à expr .
Dans la plupart des autres cas, cependant, renforcer l'expression ne fait pas de mal et peut même éviter beaucoup de problèmes. Quelques exemples de ceci:
Double substitution
set a {[exec make computer go boom]}
expr $a ; # expression string is {[exec make computer go boom]}
expr {$a} ; # expression string is {$a}
La forme non barrée exécute la substitution de commande, qui est une commande qui détruit l'ordinateur d'une manière ou d'une autre (ou qui crypte ou formate le disque dur, ou ce que vous avez). La forme contreventée effectuera une substitution de variable, puis essaiera (et échouera) de créer quelque chose de la chaîne "[exec fait exploser l'ordinateur]". Catastrophe évitée
Boucles sans fin
set i 10
while "$i > 0" {puts [incr i -1]}
Ce problème affecte à la fois for et while . Bien qu'il semble que cette boucle soit décomptée à 0 et que la sortie soit terminée, l'argument de condition à while est en fait toujours 10>0 car c'est ce que l'argument a été évalué lorsque la commande while été activée. Lorsque l'argument est accolé, il est transmis à la commande while sous la forme $i>0 , et la variable sera substituée une fois pour chaque itération. Utilisez ceci à la place:
while {$i > 0} {puts [incr i -1]}
Évaluation totale
set a 1
if "$a == 0 && [incr a]" {puts abc}
Quelle est la valeur d' a après l'exécution de ce code? Comme l'opérateur && n'évalue que l'opérande droite si l'opérande gauche est true, la valeur doit toujours être 1. Mais en fait, c'est 2. Ceci est dû au fait que l'évaluateur d'arguments a déjà effectué toutes les substitutions de variables évalué. Utilisez ceci à la place:
if {$a == 0 && [incr a]} {puts abc}
Plusieurs opérateurs (les connecteurs logiques || et && et l'opérateur conditionnel ?: :) Sont définis pour ne pas évaluer tous leurs opérandes, mais ils ne peuvent fonctionner que si la chaîne d'expression est accolée.
Multiplier une variable par 17
set myVariable [expr { $myVariable * 17 }]
Cela montre comment vous pouvez utiliser une expression simple pour mettre à jour une variable. La commande expr ne met pas à jour la variable pour vous; vous devez prendre son résultat et l'écrire dans la variable avec set .
Notez que les nouvelles lignes ne sont pas importantes dans le petit langage compris par expr , et leur ajout peut rendre les expressions plus longues plus faciles à lire.
set myVariable [expr {
$myVariable * 17
}]
Cela fait exactement la même chose cependant.
Appel d'une commande Tcl à partir d'une expression
Parfois, vous devez appeler une commande Tcl à partir de votre expression. Par exemple, en supposant que vous ayez besoin de la longueur d'une chaîne. Pour cela, il vous suffit d'utiliser une séquence dans [...] l'expression:
set halfTheStringLength [expr { [string length $theString] / 2 }]
Vous pouvez appeler n'importe quelle commande Tcl de cette façon, mais si vous appelez expr même, arrêtez! et pensez si vous avez vraiment besoin de cet appel supplémentaire. Vous pouvez généralement faire très bien en mettant l'expression interne entre parenthèses.
Erreur de mot nu non valide
Dans Tcl lui-même, il n'est pas nécessaire de citer une chaîne composée d'un seul mot. Dans le langage des chaînes d'expression que expr évalue, tous les opérandes doivent avoir un type identifiable.
Les opérandes numériques sont écrits sans aucune décoration:
expr {455682 / 1.96e4}
Donc, sont des constantes booléennes:
expr {true && !false}
La syntaxe de substitution des variables Tcl est reconnue: l'opérande sera mis à la valeur de la variable:
expr {2 * $alpha}
Il en va de même pour la substitution de commandes:
expr {[llength $alpha] > 0}
Les opérandes peuvent également être des appels de fonctions mathématiques, avec une liste d'opérandes séparés par des virgules entre parenthèses:
expr {sin($alpha)}
Un opérande peut être une chaîne entre guillemets ou en double. Une chaîne entre guillemets sera sujette à une substitution comme dans une ligne de commande.
expr {"abc" < {def}}
Si un opérande n'est pas l'un des précédents, c'est illégal. Comme il n’existe aucun indice indiquant le type de mot, expr signale une erreur de mot de passe.