Buscar..


Observaciones

Otro beneficio del uso de cadenas de expresión apuntaladas es que el compilador de bytes generalmente puede generar código más eficiente (5 - 10 veces más rápido) a partir de ellos.

Los problemas con expresiones sin apuntalar.

Es una buena práctica proporcionar argumentos de cadena de expresión como cadenas apuntaladas. El encabezado "Sustitución doble" describe razones importantes detrás de la misma.

El comando expr evalúa una cadena de expresión basada en el operador para calcular un valor. Esta cadena se construye a partir de los argumentos en la invocación.

expr 1 + 2    ; # three arguments
expr "1 + 2"  ; # one argument
expr {1 + 2}  ; # one argument

Estas tres invocaciones son equivalentes y la cadena de expresión es la misma.

Los comandos if , for , y while usan el mismo código de evaluador para sus argumentos de condición:

if {$x > 0} ...
for ... {$x > 0} ... ...
while {$x > 0} ...

La principal diferencia es que la cadena de expresión de condición siempre debe ser un único argumento.

Como con todos los argumentos en una invocación de comando en Tcl, el contenido puede o no estar sujeto a sustitución, dependiendo de cómo se citan / escapan:

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}

Hay una diferencia en el tercer y cuarto caso, ya que las barras diagonales inversas impiden la sustitución. El resultado sigue siendo el mismo, ya que el evaluador dentro de expr puede realizar la sustitución de la variable Tcl y transformar la cadena a {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!

Aquí nos metemos en problemas con el argumento preparado: cuando el evaluador en expr realiza sustituciones, la cadena de expresión ya se ha analizado en operadores y operandos, por lo que el evaluador ve una cadena que consta de dos operandos sin operador entre ellos. (El mensaje de error es " missing operator at _@_ in expression "$a _@_$b" ".)

En este caso, la sustitución de variables antes de llamar a expr evitó un error. Refuerzo del argumento impidió la sustitución de variables hasta la evaluación de la expresión, lo que provocó un error.

Pueden ocurrir situaciones como esta, más típicamente cuando una expresión para evaluar se pasa como una variable o un parámetro. En esos casos, no hay otra opción que dejar el argumento sin unir para permitir que el evaluador de argumentos "descomprima" la cadena de expresión para la entrega a expr .

Sin embargo, en la mayoría de los otros casos, el refuerzo de la expresión no hace daño y de hecho puede evitar muchos problemas. Algunos ejemplos de esto:

Doble sustitucion

set a {[exec make computer go boom]}
expr $a      ; # expression string is {[exec make computer go boom]}
expr {$a}    ; # expression string is {$a}

La forma no marcada realizará la sustitución del comando, que es un comando que destruye la computadora de alguna manera (o encripta o formatea el disco duro, o lo que sea). La forma reforzada realizará una sustitución de variable y luego intentará (y fallará) hacer que algo de la cadena "[exec make computer go boom]". Se evitó el desastre.

Bucles sin fin

set i 10
while "$i > 0" {puts [incr i -1]}

Este problema afecta tanto for como for while . Si bien parece que este bucle haría una cuenta regresiva a 0 y saldría, el argumento de condición a while en realidad siempre es 10>0 porque así se evaluó que era el argumento cuando se activó el comando while . Cuando el argumento está preparado, se pasa al comando while como $i>0 , y la variable se sustituye una vez por cada iteración. Use esto en su lugar:

while {$i > 0} {puts [incr i -1]}

Evaluación total

set a 1
if "$a == 0 && [incr a]" {puts abc}

¿Cuál es el valor de a después de ejecutar este código? Dado que el operador && solo evalúa el operando derecho si el operando izquierdo es verdadero, el valor aún debería ser 1. Pero en realidad, es 2. Esto se debe a que el evaluador de argumentos ya realizó todas las sustituciones de variables y comandos en el momento en que la cadena de expresión es evaluado Use esto en su lugar:

if {$a == 0 && [incr a]} {puts abc}

Varios operadores (las conectivas lógicas || y && , y el operador condicional ?: :) Se definen para no evaluar todos sus operandos, pero solo pueden funcionar según lo diseñado si la cadena de expresión está preparada.

Multiplicando una variable por 17

set myVariable [expr { $myVariable * 17 }]

Esto muestra cómo puedes usar una expresión simple para actualizar una variable. El comando expr no actualiza la variable por ti; necesitas tomar su resultado y escribirlo en la variable con set .

Tenga en cuenta que las nuevas líneas no son importantes en el pequeño lenguaje que entiende expr , y agregarlas puede hacer que las expresiones más largas sean mucho más fáciles de leer.

set myVariable [expr {
    $myVariable * 17
}]

Esto hace exactamente lo mismo sin embargo.

Llamando un comando Tcl desde una expresión

A veces necesitas llamar a un comando Tcl desde tu expresión. Por ejemplo, suponiendo que necesitas la longitud de una cadena. Para hacer eso, simplemente usa una [...] secuencia en la expresión:

set halfTheStringLength [expr { [string length $theString] / 2 }]

Puede llamar a cualquier comando Tcl de esta manera, pero si se encuentra a sí mismo llamando a expr , ¡deténgase! y piensa si realmente necesitas esa llamada extra. Por lo general, puedes hacerlo bien poniendo la expresión interna entre paréntesis.

Error de palabra desnuda no válido

En Tcl en sí, no es necesario citar una cadena que consiste en una sola palabra. En el lenguaje de las cadenas de expresión que expr evalúa, todos los operandos deben tener un tipo identificable.

Los operandos numéricos se escriben sin ninguna decoración:

expr {455682 / 1.96e4}

Así son las constantes booleanas:

expr {true && !false}

Se reconoce la sintaxis de sustitución de variables de Tcl: el operando se establecerá en el valor de la variable:

expr {2 * $alpha}

Lo mismo ocurre con la sustitución de comandos:

expr {[llength $alpha] > 0}

Los operandos también pueden ser llamadas a funciones matemáticas, con una lista de operandos separados por comas entre paréntesis:

expr {sin($alpha)}

Un operando puede ser una cadena entre comillas dobles o cruzada. Una cadena entre comillas dobles estará sujeta a sustitución como en una línea de comando.

expr {"abc" < {def}}

Si un operando no es uno de los anteriores, es ilegal. Como no hay ninguna pista que muestre qué tipo de palabra es, expr señala un error de palabra desnuda.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow