Every if, while and expr in an iRule evaluates an expression with the rules of 8.4.6, the base F5 names in K6091. Most of the operators behave as in any C-like language. The comparison operators do not, because Tcl values are text that may or may not read as numbers, and the operators decide at run time which kind of comparison to make.

== compares numbers when it can

The Tcl 8.4 expr manual puts it plainly: string values may be used as operands of the comparison operators, and the evaluator tries to compare them as integers or floating-point numbers when it can. In practice:

  • if both sides read as numbers, ==, !=, <, >, <= and >= compare the numbers;
  • if either side does not, they compare the two values as text;
  • eq and ne always compare text, and never convert.
ExpressionResultWhy
012 == 101012 is octal ten
012 eq 100the texts differ
"1.0" == 11both are numbers
"1.0" eq 10the texts differ
true == 10true is a boolean word, not a number, so the texts are compared
"" == 00an empty side always means a text comparison

That fallback is silent. When one side is not a number you get a text comparison and no warning, which is why a value such as 08 (not a valid number, because a leading zero means octal) makes $hour > 7 false at eight o'clock. Use eq when you mean text, convert values you mean as numbers (scan $v %d n), and keep == for values you know are numeric.

Text comparison is by character code

When values are compared as text, Tcl compares the bytes of its internal one by one. In every upper-case letter comes before every lower-case one, so "bench" < "Chair" is false: b is 98 and C is 67. Host names and paths are case-insensitive in practice, so lower-case them first:

if { [string tolower [HTTP::host]] eq "www.example.com" } {
    pool web_pool
}

string compare -nocase and string equal -nocase do the same for a single comparison.

Precedence

The Tcl 8.4 manual lists the operators in decreasing order of precedence: unary - + ~ !; then * / %; + -; << >>; < > <= >=; == !=; eq ne; &; ^; |; &&; ||; and the conditional ?:. So $a + $b * 2 is $a + ($b * 2), and $n > 5 && $m < 3 groups the comparisons before the &&.

One detail differs from the manual's table: it shows eq and ne one row below == and !=, but the Tcl 8.4.6 parser handles all four at the same level, left to right (the equality loop in generic/tclParseExpr.c accepts ==, !=, eq and ne together). "a" eq "a" == 1 is therefore ("a" eq "a") == 1, which is 1. Parentheses make the question go away, and they are kinder to the next reader anyway.

Tcl 8.4 has no power operator. 2 ** 3 is a syntax error; pow(2, 3) returns the double 8.0.

Arithmetic rules worth remembering

  • Integer division rounds toward negative infinity: 7 / -2 is -4, and -7 / 2 is -4 too.
  • The remainder takes the sign of the divisor: -7 % 2 is 1, 7 % -2 is -1.
  • Any double operand makes the operation floating point: 10 / 3 is 3, 10 / 3. is 3.33333333333.
  • && and || stop as soon as the answer is known, so in $n > 5 || [incr n] > 0 with n at 7 the incr never runs. The conditional ?: evaluates only the branch it takes.

F5's operators

F5's Operators page adds words for iRules: contains, starts_with, ends_with, equals, matches_glob and matches_regex compare text, and and, or and not are spelled versions of &&, || and !.

# F5's word operators work in iRules
if { [HTTP::uri] starts_with "/api/" and [HTTP::method] eq "POST" } {
    pool api_write_pool
}
# The style guide prefers the Tcl operator, with parentheses
if { ([HTTP::uri] starts_with "/api/") && ([HTTP::method] eq "POST") } {
    pool api_write_pool
}

F5 does not document where these words sit in the precedence table. The DevCentral iRules Style Guide asks for the Tcl operators &&, || and ! instead of the words, with parentheses to make the grouping plain, which settles the question in practice.

Brace every expression

Write expr {...} and if {...} with braces. Without them Tcl substitutes the expression text once as a command argument and again inside expr, which is slower (F5's How To Write Fast Rules puts the difference at "a factor of 20 or so") and lets a value from a request run as code. F5 K57410758 is the validator warning for exactly this, and K15650046 is the security advisory behind it.

Try it

The expression lab evaluates any expression in Tcl 8.4 or iRules mode and shows the grouping, every operand reading, and == beside eq for the same operands. The number notation converter focuses on how a single value is read.

Sources

The comparison and precedence rules are the Tcl 8.4 manual's, checked against the Tcl 8.4.6 parser source; F5's operator words, its bracing advice and the speed figure come from the F5 pages below.