Tcl DISCUSSION

Why should Tcl expr arguments be wrapped in braces, as in expr {$a + $b} instead of expr $a + $b?

Started by cristophertingcang Tcl expr bracesdouble substitutionbytecode compilationinteger divisionstring comparison eq
4 replies 248 views 5 participants
Latest activity · 30 Sep 2026

Why should Tcl expr arguments be wrapped in braces, as in expr {$a + $b} instead of expr $a + $b?

cristophertingcang Tcl Forum
#1

Both expr $a + $b and expr {$a + $b} give the same answer in my scripts, yet every style guide insists on the braced form. I also hit two odd results while converting a timing report: expr {7 / 2} gives 3, and expr {$minutes + 1} fails with an octal error when minutes is 08.

What is the real reason for the braces, and how do I avoid these numeric surprises?

Community replies 4

Re: Why should Tcl expr arguments be wrapped in braces, as in expr {$a + $b} instead of expr $a + $b?

#2

Without braces the expression is substituted twice. First the Tcl parser replaces $a and $b with their values, then expr joins its arguments into a string and parses that string again as an expression, performing its own round of variable and command substitution. With braces the parser leaves the text alone and expr does the only substitution.

The second round is a safety problem. If a holds text from a file or a user, such as [exit] or something worse, expr $a + 1 executes it as a command. expr {$a + 1} treats the value purely as data and reports that it is not a number.

Re: Why should Tcl expr arguments be wrapped in braces, as in expr {$a + $b} instead of expr $a + $b?

#3

The second reason is speed. A braced expression is a constant string, so Tcl compiles it to bytecode once and reuses it on every pass through a loop. An unbraced expression is a different string each time, so its operands must be converted to text and the whole expression re-parsed on every evaluation. In loops the braced form is commonly several times faster; you can measure your own case with time {expr {$a + $b}} 100000 against the unbraced version.

The same rule applies to the conditions of if, while and for, which are evaluated by the same expression engine: always brace them.

Re: Why should Tcl expr arguments be wrapped in braces, as in expr {$a + $b} instead of expr $a + $b?

#4

The division result is integer arithmetic: when both operands are integers, / gives an integer, so expr {7 / 2} is 3. Make one operand a floating-point value, expr {7 / 2.0} or expr {double($n) / $d}, to get 3.5. Note that Tcl rounds integer division toward negative infinity, so expr {-7 / 2} is -4, not -3 as in C, and expr {-7 % 2} is 1.

To control how a result is displayed, use format: format %.3f [expr {10 / 3.0}] gives 3.333.

Re: Why should Tcl expr arguments be wrapped in braces, as in expr {$a + $b} instead of expr $a + $b?

#5

The 08 failure is because Tcl 8 reads an integer with a leading zero as octal, and 8 is not an octal digit; 010 would silently become 8. This bites whenever you parse times, dates or zero-padded indices. Strip the padding by scanning as decimal: scan $minutes %d m stores 8 in m. Tcl 9 no longer treats a bare leading zero as octal, but many engineering tools embed Tcl 8.x, so write code that is safe for both.

A related habit: compare strings with eq and ne, not ==. The == operator compares numerically when both sides look like numbers, so expr {"1.0" == "1"} is true; for version strings and names that is rarely what you want.

TEP COMMUNITY