# Tcl Programming/expr

### Overview

Arithmetic and logical operations (plus some string comparisons) are in
Tcl concentrated in the **expr** command. It takes one or more
arguments, evaluates them as an expression, and returns the result. The
language of the **expr** command (also used in condition arguments of
the **if**, **for**, **while** commands) is basically equivalent to C\'s
expressions, with infix operators and functions. Unlike C, references to
variables have to be done with *\$var*. Examples:

`set a [expr {($b + sin($c))/2.}]`\
`if {$a > $b && $b > $c} {puts "ordered"}`\
`for {set i 10} {$i >= 0} {incr i -1} {puts $i...} ;# countdown`

The difference between Tcl syntax and *expr* syntax can be contrasted
like this:

`[f $x $y]  ;# Tcl:  embedded command`\
` f($x,$y)  ;# expr: function call, comma between arguments`

In another contrast to Tcl syntax, whitespace between \"words\" is
optional (but still recommended for better readability :) And string
constants must always be quoted (or braced if you wish):

`if {$keyword eq "foo"} ...`

Then again, Tcl commands can always be embedded into expressions, in
square brackets as usual:

`proc max {x y} {expr {$x>$y? $x: $y}}`\
`expr {[max $a $b] + [max $c $d]}`

In expressions with numbers of mixed types, integers are coerced to
doubles:

`% expr 1+2.`\
`3.0`

It is important to know that division of two integers is done as integer
division:

`% expr 1/2`\
`0`

You get the (probably expected) floating-point division if at least one
operand is *double*:

`% expr 1/2.`\
`0.5`

If you want to evaluate a string input by the user, but always use
floating-point division, just transform it, before the call to expr, by
replacing \"/\" with \"\*1./\" (multiply with floating-point 1. before
every division):

`expr [string map {/ *1./} $input]`

### Brace your expressions

In most cases it is safer and more efficient to pass a single braced
argument to *expr*. Exceptions are:

-   no variables or embedded commands to substitute
-   operators or whole expressions to substitute

The reason is that the Tcl parser parses unbraced expressions, while
expr parses that result again. This may result in success for malicious
code exploits:

`% set e {[file delete -force *]}`\
`% expr $e   ;# will delete all files and directories`\
`% expr {$e} ;# will just return the string value of e`

That braced expressions evaluate much faster than unbraced ones, can be
easily tested:

`% proc unbraced x {expr  $x*$x}`\
`% proc braced x   {expr {$x*$x}}`\
`% time {unbraced 42} 1000`\
`197 microseconds per iteration`\
`% time {braced 42} 1000`\
`34 microseconds per iteration`

The precision of the string representation of floating-point numbers is
also controlled by the tcl_precision variable. The following example
returns nonzero because the second term was clipped to 12 digits in
making the string representation:

`% expr 1./3-[expr 1./3]`\
`3.33288951992e-013`

while this braced expression works more like expected:

`% expr {1./3-[expr 1./3]}`\
`0.0`

### Operators

Arithmetic, bitwise and logical operators are like in C, as is the
conditional operator found in other languages (notably C):

-   c?a:b \-- if c is true, evaluate a, else b

The conditional operator can be used for compact functional code (note
that the following example requires Tcl 8.5 so that fac() can be called
inside its own definition):

`% proc tcl::mathfunc::fac x {expr {$x<2? 1 : $x*fac($x-1)}}`\
`% expr fac(5)`\
`120`

#### Arithmetic operators

The arithmetic operators are also like those found in C:

-   \+ addition
-   \- (binary: subtraction. unary: change sign)
-   \* multiplication
-   / (integer division if both operands are integer
-   \% (modulo, only on integers)
-   \*\* power (available from Tcl 8.5)

#### Bitwise operators

The following operators work on integers only:

-   & (AND)
-   \| (OR)
-   \^ (XOR)
-   \~ (NOT)
-   \<\< shift left
-   \>\> shift right

#### Logical operators

The following operators take integers (where 0 is considered false,
everything else true) and return a truth value, 0 or 1:

-   && (and)
-   \|\| (or)
-   ! (not - unary)

#### Comparison operators

If operands on both side are numeric, these operators compare them as
numbers. Otherwise, string comparison is done. They return a truth
value, 0 (false) or 1 (true):

-   == equal
-   != not equal
-   \> greater than
-   \>= greater or equal than
-   \< less than
-   \<= less or equal than

As truth values are integers, you can use them as such for further
computing, as the sign function demonstrates:

`proc sgn x {expr {($x>0) - ($x<0)}}`\
`% sgn 42`\
`1`\
`% sgn -42`\
`-1`\
`% sgn 0`\
`0`

#### String operators

The following operators work on the string representation of their
operands:

-   eq string-equal
-   ne not string-equal

Examples how \"equal\" and \"string equal\" differ:

`% expr {1 == 1.0}`\
`1`\
`% expr {1 eq 1.0}`\
`0`

#### List operators

From Tcl 8.5, the following operators are also available:

-   a **in** b - 1 if a is a member of list b, else 0
-   a **ni** b - 1 if a is not a member of list b, else 0

Before 8.5, it\'s easy to write an equivalent function

`proc in {list el} {expr {[lsearch -exact $list $el]>=0}}`

Usage example:

`if [in $keys $key] ...`

which you can rewrite, once 8.5 is available wherever your work is to
run, with

`if {$key in $keys} ...`

### Functions

The following functions are built-in:

-   abs(x) - absolute value
-   acos(x) - arc cosine. acos(-1) = 3.14159265359 (Pi)
-   asin(x) - arc sine
-   atan(x) - arc tangent
-   atan2(y,x)
-   ceil(x) - next-highest integral value
-   cos(x) - cosine
-   cosh(x) - hyperbolic cosine
-   double(x) - convert to floating-point number
-   exp(x) - e to the x-th power. exp(1) = 2.71828182846 (Euler number,
    e)
-   floor(x) - next-lower integral value
-   fmod(x,y) - floating-point modulo
-   hypot(y,x) - hypotenuse (sqrt(\$y\*\$y+\$x\*\$x), but at higher
    precision)
-   int(x) - convert to integer (32-bit)
-   log(x) - logarithm to base e
-   log10(x) - logarithm to base 10
-   pow(x,y) - x to the y-th power
-   rand() - random number \> 0.0 and \< 1.0
-   round(x) - round a number to nearest integral value
-   sin(x) - sine
-   sinh(x) - hyperbolic sine
-   sqrt(x) - square root
-   srand(x) - initialize random number generation with seed x
-   tan(x) - tangent
-   tanh(x) - hyperbolic tangent
-   wide(x) - convert to wide (64-bit) integer

Find out which functions are available with *info functions*:

`% info functions`\
`round wide sqrt sin double log10 atan hypot rand abs acos atan2 srand`\
`sinh floor log int tanh tan asin ceil cos cosh exp pow fmod`

### Exporting expr functionalities

If you don\'t want to write expr {\$x+5} every
time you need a little calculation, you can easily export operators as
Tcl commands:

`foreach op {+ - * / %} {proc $op {a b} "expr {\$a $op \$b}"}`

After that, you can call these operators like in LISP:

`% + 6 7`\
`13`\
`% * 6 7`\
`42`

Of course, one can refine this by allowing variable arguments at least
for + and \*, or the single-argument case for -:

`proc - {a {b ""}} {expr {$b eq ""? -$a: $a-$b}}`

Similarly, expr functions can be exposed:

`foreach f {sin cos tan sqrt} {proc $f x "expr {$f($x)}"}`

In Tcl 8.5, the operators can be called as commands in the
*::tcl::mathop* namespace:

`% tcl::mathop::+ 6 7`\
`13`

You can import them into the current namespace, for shorthand math
commands:

`% namespace import ::tcl::mathop::*`\
`% + 3 4 ;# way shorter than [expr {3 + 4}]`\
`7`\
`% * 6 7`\
`42`

### User-defined functions

From Tcl 8.5, you can provide procs in the *::tcl::mathfunc* namespace,
which can then be used inside *expr* expressions:

`% proc tcl::mathfunc::fac x {expr {$x < 2? 1: $x * fac($x-1)}}`\
`% expr fac(100)`\
`93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000`

This is especially useful for recursive functions, or functions whose
arguments need some expr calculations:

`% proc ::tcl::mathfunc::fib n {expr {$n<2? 1: fib($n-2)+fib($n-1)}} `\
`% expr fib(6)`\
`13`

