tcl
espressioni
Ricerca…
Osservazioni
Un altro vantaggio derivante dall'uso di stringhe di espressione rinforzate è che il compilatore di byte in genere è in grado di generare codice più efficiente (da 5 a 10 volte più veloce).
I problemi con espressioni non vincolate
È una buona pratica fornire argomenti stringa di espressione come stringhe rinforzate. L'intestazione "Doppia sostituzione" delinea importanti motivi alla base dello stesso.
Il comando expr valuta una stringa di espressione basata sull'operatore per calcolare un valore. Questa stringa è costruita dagli argomenti nell'invocazione.
expr 1 + 2 ; # three arguments
expr "1 + 2" ; # one argument
expr {1 + 2} ; # one argument
Queste tre invocazioni sono equivalenti e la stringa di espressione è la stessa.
I comandi if , for e while utilizzano lo stesso codice di valutazione per i loro argomenti di condizione:
if {$x > 0} ...
for ... {$x > 0} ... ...
while {$x > 0} ...
La differenza principale è che la stringa di espressione della condizione deve sempre essere un singolo argomento.
Come per ogni argomento in una chiamata di comando in Tcl, il contenuto può o non può essere sottoposto a sostituzione, a seconda di come sono quotati / fuggiti:
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}
C'è una differenza nel terzo e nel quarto caso in quanto le barre rovesciate / parentesi graffe impediscono la sostituzione. Il risultato è sempre lo stesso, poiché il valutatore interno a expr può eseguire la sostituzione della variabile Tcl e trasformare la stringa in {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!
Qui ci troviamo nei guai con l'argomento rinforzato: quando il valutatore in expr esegue sostituzioni, la stringa di espressione è già stata analizzata in operatori e operandi, quindi ciò che il valutatore vede è una stringa composta da due operandi senza operatore tra di loro. (Il messaggio di errore è " missing operator at _@_ in expression "$a _@_$b" ".)
In questo caso, la sostituzione di variabili prima di expr veniva chiamata prevenuta un errore. Il mantenimento dell'argomento ha impedito la sostituzione della variabile fino alla valutazione dell'espressione, che ha causato un errore.
Situazioni come questa possono verificarsi, in genere quando un'espressione da valutare viene passata come variabile o parametro. In questi casi non c'è altra scelta che lasciare l'argomento non vincolato per consentire all'applicatore di valutazioni di "decomprimere" la stringa di espressione per la consegna a expr .
Nella maggior parte degli altri casi, tuttavia, il rinforzo dell'espressione non nuoce e anzi può evitare un sacco di problemi. Alcuni esempi di questo:
Doppia sostituzione
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 non vincolata eseguirà la sostituzione del comando, che è un comando che distrugge il computer in qualche modo (o crittografa o formatta l'hard disk, o cosa hai). La forma rinforzata eseguirà una sostituzione variabile e quindi tenterà (e fallirà) di creare qualcosa della stringa "[exec make computer go boom]". Disastro evitato
Loop senza fine
set i 10
while "$i > 0" {puts [incr i -1]}
Questo problema interessa sia for che while . Anche se sembra che questo ciclo possa contare fino a 0 e uscire, l'argomento condizione a while è in realtà sempre 10>0 perché era quello che l'argomento veniva valutato quando veniva attivato il comando while . Quando l'argomento è rinforzato, viene passato al comando while come $i>0 e la variabile verrà sostituita una volta per ogni iterazione. Usa questo invece:
while {$i > 0} {puts [incr i -1]}
Valutazione totale
set a 1
if "$a == 0 && [incr a]" {puts abc}
Qual è il valore di a dopo aver eseguito questo codice? Poiché l'operatore && valuta solo l'operando di destra se l'operando di sinistra è true, il valore dovrebbe essere ancora 1. Ma in realtà, è 2. Questo perché l'analizzatore di argomenti ha già eseguito tutte le sostituzioni di variabili e comandi nel momento in cui la stringa di espressione è valutata. Usa questo invece:
if {$a == 0 && [incr a]} {puts abc}
Diversi operatori (i connettivi logici || e && e l'operatore condizionale ?: :) Sono definiti per non valutare tutti i loro operandi, ma possono funzionare solo come progettati se la stringa di espressione è rinforzata.
Moltiplicare una variabile per 17
set myVariable [expr { $myVariable * 17 }]
Questo mostra come puoi usare un'espressione semplice per aggiornare una variabile. Il comando expr non aggiorna la variabile per te; è necessario prendere il suo risultato e scriverlo alla variabile con set .
Nota che i newline non sono importanti nel linguaggio piccolo compreso da expr , e aggiungerli può rendere le letture più lunghe molto più facili da leggere.
set myVariable [expr {
$myVariable * 17
}]
Questo fa esattamente la stessa cosa però.
Chiamare un comando Tcl da un'espressione
A volte è necessario chiamare un comando Tcl dalla propria espressione. Ad esempio, supponendo di aver bisogno della lunghezza di una stringa. Per fare ciò, basta usare una [...] sequenza nell'espressione:
set halfTheStringLength [expr { [string length $theString] / 2 }]
Puoi chiamare qualsiasi comando Tcl in questo modo, ma se ti ritrovi a chiamare expr , fermati! e pensa se hai davvero bisogno di quella chiamata in più. Di solito puoi fare bene mettendo l'espressione interiore tra parentesi.
Errore bareword non valido
In Tcl, una stringa composta da una singola parola non ha bisogno di essere citata. Nella lingua delle stringhe di espressione che expr valuta, tutti gli operandi devono avere un tipo identificabile.
Gli operandi numerici sono scritti senza alcuna decorazione:
expr {455682 / 1.96e4}
Quindi le costanti booleane:
expr {true && !false}
La sintassi di sostituzione variabile Tcl è riconosciuta: l'operando verrà impostato sul valore della variabile:
expr {2 * $alpha}
Lo stesso vale per la sostituzione di comando:
expr {[llength $alpha] > 0}
Gli operandi possono anche essere chiamate di funzioni matematiche, con un elenco di operandi separati da virgole tra parentesi:
expr {sin($alpha)}
Un operando può essere una stringa doppia quotata o rinforzata. Una stringa doppia citazione sarà soggetta a sostituzione proprio come in una riga di comando.
expr {"abc" < {def}}
Se un operando non è uno dei precedenti, è illegale. Poiché non vi è alcun suggerimento che mostri che tipo di parola sia, expr segnala un errore bareword.