expr(3tcl)

NAZWA
expr - Oblicz wyrażenie

SKŁADNIA
expr arg ?arg arg ...?

OPIS

Łączy kolejne parametry arg (dodając między nimi spacje) i analizuje wynik jako wyrażenie Tcl, zwracając wartość. Dozwolone wyrażenia Tcl są podzbiorem operatorów dozwolonych w wyrażeniach C i mają takie samo znaczenie i pierwszeństwo, jak odpowiadające im operatory C. Wyrażenia dają prawie zawsze wyniki numeryczne (całkowite, lub zmiennoprzecinkowe). Np. wyrażenie expr 8.2 + 6 przechodzi w 14.2. Wyrażenia Tcl różnią się od wyrażeń C tym, że operandy są podawane w inny sposób. Poza tym, wyrażenia Tcl obsługują operandy nienumeryczne oraz porównania łańcuchów.

OPERANDY

Wyrażenie Tcl składa się z kombinacji operandów, operatorów i nawiasów. Między operandami i operatorami można używać białych spacji; są one ignorowane. Tam gdzie mozliwe, operandy są interpretowane jako wartości całkowite. Wartości całkowite można podawać dziesiętnie (normalny wypadek), ósemkowo (jeśli pierwszym znakiem operandu jest 0) lub szesnastkowo (jeśli pierwszymi znakami operandu są 0x). Jeśli operand nie jest w żadnym z powyszszych formatów całkowitych, to o ile jest to możliwe, jest traktowany jako liczba zmiennoprzecinkowa. Zmienne zmiennoprzecinkowe mogą być podawane w dowolny ze sposobów, obsługiwanych przez zgodny z ANSI kompilator C (poza tym, że przyrostki f, F, l i L w większości instalacji nie będą dozwolone). Na przykład, wszystkie następujące liczby są poprawnymi liczbami zmiennoprzecinkowymi: 2.1, 3., 6e4, 7.91e+16. Jesli nie jest możliwa interpretacja numeryczna, to operand jest pozostawiany jako łańcuch (wtedy jednak można stosować tylko ograniczony zestaw operatorów).

Operandy mogą być podawane w następujące sposoby:

[1] Jako wartość numeryczną, całkowitą albo zmiennoprzecinkową.

[2] Jako zmienną Tcl, przy użyciu standardowej notacji $. Wartość zmiennej zostanie wykorzystana jako operand.

[3] Jako łańcuch ujęty w podwójne cudzysłowy. Przetwarzanie wyrażenia będzie wrażliwe na podstawienia ukośnikowe, zmiennych i komend, i użyje wyniku jako operandu.

[4] Jako łańcuch ujęty w nawiasy klamrowe. Znaki między klamrą otwierającą i zamykającą zostaną użyte jako operand bez żadnego podstawiania.

[5] Jako komenda Tcl w naiwasach kwadratowych. Komenda zostanie wykonana, a jej wynik użyty jako operand.

[6] Jako funkcja matematyczna, której argumenty mają dowolną z powyższych postaci, taka jak sin($x). Zobacz niżej dla listy zdefiniowanych funkcji.

Tam gdzie zachodzą podstawienia, są one dokonywane przez instrukcje wyrażenia. Jednak mógł też zostać już wykonany inny poziom podstawiania, dokonywany przez przetwarzacza poleceń przed wywołaniem przetwarzacza wyrażeń. Jak pokazuje poniższa dyskusja, zwykle najlepiej jest ujmować wyrażenia w klamry, co zapobiega by przetwarzacz dokonał podstawień zawartości.

Dla pewnych przykładów prostych wyrażeń, załóżmy że zmienna a ma wartość 3, a zmienna b wartość 6. Następnie, komenda po lewej stronie każdej z linii da wynik, widoczny po prawej stronie.
expr 3.1 + $a    6.1
expr 2 + "$a.$b"    5.6
expr 4*[llength "6 2"]    8
expr {{word one} < "word $a"}    0

OPERATORY

Poniżej wymienione są prawidłowe operatory; są one zgrupowane według malejącego priorytetu:

-  +  ~  !
    Jednoargumentowy minus, jednoargumentowy plis, bitowy NOT i logiczny NOT. Żaden z tych operatorów nie może być stosowany do operandów łańcuchowych, a bitowy NOT może być stosowany tylko do liczb całkowitych.

*  /  %
    Mnożenie, dzielenie, reszta. Żaden z tych operatorów nie może być stosowany do operandów łańcuchowych, a reszta może być stosowana tylko do liczb całkowitych. Reszta ma zawsze znak dzielnika i jej wartość absolutna jest zawsze mnijesza niż wartość dzielnika.

+  -
    Dodawanie i odejmowanie. Prawidłowe dla dowolnych operandów numerycznych.

<<  >>
    Przesuwanie w lewo i w prawo. Prawidłowe tylko dla operandów całkowitych. Przesuwanie w prawo propaguje bit znaku.

<  >  <=  >=
    Logiczny mniejszy, większy, mniejszy lub równy, większy lub równy. Każdy operator daje 1 jeśli warunek jest spełniony lub 0 w przeciwnym wypadku. Operandami mogą być zarówno wartości numeryczne, jak i łańcuchowe, w którym wypadku dokonywane jest porównywanie łańcuchów.

==  !=
    Logiczna równość i nierówność. Każdy operator daje wynik zero/jeden. Prawidłowe dla wszelkich operandów.

&   Bitowy AND. Prawidłowy tylko dla operandów całkowitych.

^   Bitowy XOR. Prawidłowy tylko dla operandów całkowitych.

|   Bitowy OR. Prawidłowy tylko dla operandów całkowitych.

&&  Logiczny AND. Daje 1 jeśli obydwa operandy są niezerowe, lub 0 w przeciwnym wypadku. Prawidłowe dla operandów logicznych i numerycznych.

||  Logiczny OR. Daje 0 jeśli obydwa operandy są zerowe lub 1 w przeciwnym wypadku. Prawidłowe dla operandów logicznych i numerycznych.

x?y:z
    Jeżeli-to-inaczej, jak w C. Jeśli x rozwija się na wartość niezerową, to wynikiem jest wartość y. W przeciwnym wypadku wartością wynikową jest z. Operand x musi mieć wartość numeryczną.

Zobacz podręcznik C dla dalszych szczegółów o wynikach, dawanych przez operatory. Wszystkie operatory binarne grupują się od lewej do prawej w tym samym priorytecie. Np. komenda expr 4*2 < 7 daje 0.

Operatory &&, || i ?: mają ``leniwą analizę'', zupełnie jak w C, co znaczy, że operandy nie są analizowane jeśli nie ma takiej potrzeby do określenia wyniku. Np. w komendzie expr {$v ? [a] : [b]} analizowane będzie tylko jedno z [a] lub [b], zależnie od wartości $v. Zauważ jednak, że jest to prawdziwe tylko jeśli całe wyrażenie jest ujęte w nawiasy klamrowe; w przeciwnym wypadku przetwarzacz Tcl przemieli zarówno [a] jak i [b] jeszcze przed wywołaniem komendy expr.

FUNKCJE MATEMATYCZNE

Tcl obsługuje następujące funkcje matematyczne wyrażeń:
acos | cos | hypot | sinh
asin | cosh | log | sqrt
atan | exp | log10 | tan
atan2 | floor | pow | tanh
ceil | fmod | sin
Każda z tych funkcji woła funkcję biblioteki matematycznej o tej samej nazwie. Tcl ponadto implemntuje następujące funkcje dla konwersji między liczbami całkowitymi, zmiennoprzecinkowymi i losowania liczb losowych:

abs(arg)
    Zwraca wartość modułu arg. Arg może być liczbą całkowitą, lub zmiennoprzecinkową; wynik jest zwracany w tej samej postaci.

double(arg)
    Jeśli arg jest liczbą zmiennoprzecinkową, zwracane jest arg. W przeciwnym wypadku arg jest konwertowany na postać zmiennoprzecinkową i zwracany w tej postaci.

int(arg)
    Jak wyżej, ale zamiana na liczbę całkowitą.

rand()
    Zwraca liczbę zmiennoprzecinkową w zakresie od zera do 1. Nasienie pochodzi z wewnętrznego zegara maszyny, lub może być ustawiane ręcznie funkcją srand.

round(arg)
    Jeśli arg jest całkowite, zwracane jest arg. W przeciwnym wypadku arg jest konwertowane na postać całkowitą poprzez zaokrąglanie.

srand(arg)
    Parametr arg, który musi być liczbą całkowitą, służy do resetowania nasienia generatora liczb losowych. Zwraca pierwszą liczbę losową dla tego nasienia. Każdy interpreter ma swoje własne nasienie.

W dodatku do tych predefiniowanych funkcji, aplikacje mogą definiować inne funkcje, korzystając z Tcl_CreateMathFunc().

TYPY, PRZEPEŁNIENIE I PRECYZJA

Wszystkie obliczenia wewnętrzne na liczbach całkowitych są dokonywane w typie long z C, a wszystkie obliczenia zmiennoprzecinkowe na typie double. Podczas konwersji łańcucha na liczbę zmiennoprzecinkową, wykrywane jest przepełnienie eksponentne, co powoduje błąd Tcl. Dla konwersji łańcucha na liczbę całkowitą, wykrywanie przepełnienia zależy od zachowania pewnych funkcji biblioteki C, więc raczej nie można na tym polegać.

Konwersja między reprezentacjami całkowitymi, zmiennoprzecinkowymi i łańcuchowymi operandów jest wykonywana automatycznie tam gdzie potrzeba. Dla obliczeń arytmetycznych zmienne całkowite są używane tak długo, aż nie pojawi się liczba zmiennoprzecinkowa i wtedy zaczyna się używanie liczb zmiennoprzecinkowych. Na przykład, expr 5 / 4 zwraca 1, podczas gdy expr 5 / 4.0 expr 5 / ( [string length "abcd"] + 0.0 ) zwraca 1.25. Wartości zmiennoprzecinkowe są zawsze zwracane z ``.'' lub e, więc nie wyglądają jak liczby całkowite. Na przykład, expr 20.0/5.0 zwraca 4.0, nie 4.

OPERACJE ŁAŃCUCHOWE

Jeśli jeden z operandów porównania jest łańcuchem, a drugi ma wartość numeryczną, to operand numeryczny jest konwertowany z użyciem formatu %d lub %g funkcji sprintf(3) języka C z powrotem na łańcuch. Na przykład komendy expr {"0x03" > "2"} expr {"0y" < "0x12"} zwracają 1. Pierwsze porównanie jest dokonywane w porównaniu całkowitym, a drugie w porównaniu łańcuchowym, po przekonwertowaniu drugiego operandu na łańcuch 18. Ponieważ Tcl ma tendencje do traktowania wartości tam gdzie możliwe jako liczby, to używanie operatorów == i podobnych nie jest dobrym pomysłem, jeśli naprawdę chcesz porównania łańcuchowego; lepiej użyć komendy string compare.

ROZWAŻANIA O WYDAJNOŚCI

Jeśli chcesz jak największej szybkości i najmniejszego zajmowania pamięci, ujmuj wyrażenia w klamry. Umożliwia to kompilatorowi kodu bitowego Tcl wygenerowanie jak najlepszego kodu.

Jak wspomniano wyżej, w wyrażeniach dokonuje się dwóch podstawień: raz przez przetwarzacz Tcl, raz przez komendę expr. Na przykład, komendy set a 3 set b {$a + 2} expr $b*4 zwracają 11, a nie wielokrotność 4. Jest tak dlatego, że przetwarzacz Tcl najpierw podstawia za $a + 2 zmienną b, a następnie komenda expr przetwarza wyrażanie $a + 2*4.

Większość wyrażeń nie wymaga drugiej kolejki podstawień. Są one albo ujmowane w klamry, albo ich proces podstawiania zmiennych i komend daje liczby i łańcuchy, nie wymagające podstawień jako takich. Jednak z uwagi na to, że nieuklamrowione wyrażenia wymagają dwóch rund podstawień, kompilator kodu bitowego musi emitować dodatkowe instrukcje obsługi takiej sytuacji. Najkosztowniejszy kod generowany jest dla nieuklamrowionych wyrażeń, które zawierają podstawienia komend. Wyrażenia te muszą być implementowane przez generowanie nowego kodu za każdym wykonaniem wyrażenia.

SŁOWA KLUCZOWE
arytmetyka, logiczny, porównanie, wyrażenie, porównanie rozmyte