« Tcl: Sostituzione e valutazioneAppunti di Tcl/TkTcl: Controllo del flusso: comando if »

Tcl

Espressioni matematiche

A differenza di C o Perl e similari, che prevedono nella loro sintassi l'incorporazione delle espressioni matematiche, Tcl richiede un comando speciale per valutare le espressioni matematiche, il comando expr(n). Strettamente parlando le espressioni matematiche non fanno parte del linguaggio Tcl, per lo meno a livello sintattico.

expr(n) accetta un numero variabile di argomenti, ma ci deve essere almeno un argomento. Internamente expr(n) concatena tutti gli argomenti che gli vengono forniti (come risultano dopo la fase di sostituzione), aggiungendo degli spazi separatori tra un argomento e un'altro, ottenendo un'unica stringa, che viene analizzata e valutata come una espressione matematica. Infine expr(n) restituisce il risultato della valutazione, che è una stringa, essendo questo l'unico tipo di dati in Tcl. Le espressioni restituiscono comunque valori interi o a virgola mobile che sono rappresentati tramite stringhe. Le operazioni di tipo logico ritornano solo le stringhe 0 e 1 che stanno rispettivamente per falso (false) e vero (true).

Una espressione matematica in Tcl può consistere di operandi, operatori e parentesi tonde. Tra questi elementi lessicali possono essere intercalati spazi bianchi a piacimento, che vengono ignorati.

Gli operatori in Tcl sono un sottoinsieme di quelli del linguaggio C, con lo stesso significato e con le stesse regole di precedenza e associatività del C.

Gli operandi possono essere valori interi o a virgola mobile, valori di variabili (come visto, a differenza del C, i valori delle variabili si ottengono prefissando il loro nome con $). Un'altra differenza rispetto al C è che in Tcl gli operandi possono essere anche non numerici. expr(n) permette infatti di effettuare confronti anche tra le stringhe.

I valori interi che non iniziano con uno zero sono considerati in base 10 (decimale), mentre se il primo carattere è 0 e il secondo un'altra cifra, il valore si intende in base 8 (ottale), invece se i primi due caratteri sono 0x allora il valore si intende in base 16 (esadecimale), esattamente come in C. Non confondete l'uso delle sequenze di escape generalizzate che consentono di sostituire il codice ottale o esadecimale di un carattere col carattere stesso durante la fase di sostituzione effettuata dall'interprete prima della valutazione, con le conversioni di base che effettua invece internamente il comando expr(n), in quanto sono funzionalità differenti. Ad esempio \x20 indica il carattere spazio in ASCII, mentre un 0x20 che viene interpretato come operando da expr(n), è il numero decimale intero 32.

I valori in virgola mobile possono essere specificati con gli stessi formati utilizzati dal linguaggio C. Ad esempio la carica di un elettrone in coulomb può essere indicata da 1.6e-19. Il . può non essere preceduto o seguito da una cifra e in al caso si intende che c'è uno zero:

% expr .4
0.4
% expr 4.
4.0

Dove possibile gli operandi sono interpretati come valori interi, quindi non viene utilizzata l'aritmetica a virgola mobile se non necessario. Se un operando non è un numero intero o floating point valido, verrà considerato come una stringa, tra cui si può applicare solo un set ristretto di operatori.

Le parentesi servono per alterare l'ordine di valutazione rispetto all'ordine di precedenza predefinito e fissato degli operatori.

L'istruzione expr(n) effettua internamente la sostituzione dei valori delle variabili quando si trova di fronte ad un operando che inizia col carattere $. In questo senso si comporta diversamente dalle altre istruzioni:

% set e 1.6e-19
1.6e-19
% puts {$e}
$e
% expr {$e}
1.6e-19

Il parser di expr(n) effettua anche la sostituzione dei comandi racchiusi tra [ ]. Questo permette di utilizzare come operando il risultato di un altro comando Tcl, complicato quanto si vuole. Per gli operandi non numerici racchiusi tra doppi apici il parser effettua le sostituzioni di variabile, del backslash e dei comandi, mentre non effettua alcuna sostituzione per quelli racchiusi tra parentesi graffe:

% set a 1
% expr {{$a}}
$a
% expr {"$a"}
1

La tabella seguente indica, in ordine di precedenza decrescente, tutti gli operatori riconosciuti da expr(n) e il loro significato. Gli operatori che hanno uguale precedenza sono listati insieme sulla stessa riga:

operatori descrizione applicazione
- + ~ ! meno e più unari, NOT bit a bit e NOT booleano operandi numerici; ~ solo per gli interi
* / % moltiplicazione, divisione e resto operandi numerici; % solo per gli interi
+ - somma e sottrazione operandi numerici
<< >> shift destro e sinistro operandi interi
< > <= >= minore, maggiore, minore o uguale e maggiore o uguale (booleani) sia operandi numerici che non
== != uguale e non uguale (booleani) sia operandi numerici che non
& AND bit-a-bit operandi interi
^ OR esclusivo bit-a-bit operandi interi
| OR bit-a-bit operandi interi
&& AND (booleano) operandi numerici
|| OR (booleano) operandi numerici
x?y:z if-then-else x deve essere numerico

Per quanto riguarda il resto della divisione, esistono diverse possibili definizioni. Quella adottata da Tcl è quella secondo cui il quoziente q e il resto r interi della divisione di due interi m e n sono definiti in modo che sia sempre soddisfatta la seguente proposizione:

(m == q*n + r) && (sign(r)=sign(n)) && (abs(r)<abs(n))

L'operatore di shift a destra >> propaga sempre il bit di segno. Questo significa che ad esempio -10 >> 1 == -5, quindi >> 1 equivale ad una divisione intera per 2.

Operatori logici come !, && e || considerano un operando numerico (intero o floating point) diverso da zero come true e solo il valore zero come false.

L'operatore ternario di selezione ?: è stato mutuato dal C. Il suo comportamento è lo stesso: se x ha un valore diverso da zero, allora il risultato è y, altrimenti il risultato è il valore di z.

Un operando di expr(n) può eanche essere il risultato di una funzione matematica, i cui argomenti sono a loro volta degli operandi; la maggior parte delle funzioni hanno un solo operando, alcune due e qualcuna nessuno. Le funzioni matematiche supportate dal parser di expr(n) sono meglio descritte nella manpage, qui ci limitiamo ad elencarle.

abs(arg)         cosh(arg)        log(arg)        sqrt(arg)
acos(arg)        double(arg)      log10(arg)      srand(arg)
asin(arg)        exp(arg)         pow(x, y)       tan(arg)
atan(arg)        floor(arg)       rand()          tanh(arg)
atan2(x, y)      fmod(x, y)       round(arg)
ceil(arg)        hypot(x, y)      sin(arg)
cos(arg)         int(arg)         sinh(arg)

I programmatori C riconosceranno che le funzioni sono più o meno le stesse della libreria matematica del C. Sono state aggiunte delle funzioni per operare le conversioni fra numeri di insiemi matematici diversi:

abs double int round

Ecco un programma di esempio che le illustra:

set x -1.75
puts "abs($x)=[expr abs($x)]"
puts "double($x)=[expr double($x)]"
puts "int($x)=[expr int($x)]"
puts "round($x)=[expr round($x)]"
risultato:
abs(-1.75)=1.75
double(-1.75)=-1.75
int(-1.75)=-1
round(-1.75)=-2

« Tcl: Sostituzione e valutazioneAppunti di Tcl/TkTcl: Controllo del flusso: comando if »